Skip to content

Improve level scheduling: HashSet-based addLevels, cycle detection, ExecutorService for triggers - #53

Open
Avi1235 wants to merge 1 commit into
armory-plugins:mainfrom
Avi1235:improve-level-scheduling
Open

Avi1235 wants to merge 1 commit into
armory-plugins:mainfrom
Avi1235:improve-level-scheduling

Conversation

@Avi1235

@Avi1235 Avi1235 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

This PR improves the DAG-leveling logic in UtilityHelper and how RunMultiplePipelinesTask triggers child pipelines within a level.

Changes:

  • UtilityHelper.addLevels: switched from repeated List.contains/containsAll scans to a HashSet for O(1) membership checks, and converted the recursion to an iterative loop to remove StackOverflowError risk on long dependency chains.
  • Added cycle detection: throws IllegalStateException naming the specific apps that never became schedulable if depends_on forms a circular dependency (previously this failed silently).
  • UtilityHelper.getGraphOfApps: throws a clear IllegalArgumentException instead of a bare NullPointerException when depends_on references an app name that does not exist in the yaml config.
  • RunMultiplePipelinesTask: replaced the raw Thread list + join() with a fixed ExecutorService sized to the level. Same per-level parallelism as before, but exceptions from triggerThread now surface via stage.appendErrorMessage instead of dying silently on a background thread, and the interrupt flag is restored correctly instead of swallowed.
  • Updated call sites and existing unit tests for the new addLevels signature; added two regression tests covering the new cycle-detection and unresolved-dependency error paths.

Testing: Verified by hand against the existing UtilityHelperTest cases. Please run in CI before merging.

…xecutorService for triggers

- UtilityHelper.addLevels: switch from List.contains/containsAll scans to a
  HashSet for O(1) membership checks; convert recursion to an iterative loop
  to remove StackOverflowError risk on long dependency chains; throw
  IllegalStateException with the stuck app names when a circular depends_on
  prevents some apps from ever becoming schedulable.
- UtilityHelper.getGraphOfApps: throw a clear IllegalArgumentException instead
  of a bare NullPointerException when depends_on references an app name that
  doesn't exist in the yaml config.
- RunMultiplePipelinesTask: replace the raw Thread list + join() with a fixed
  ExecutorService sized to the level, using Future#get() per app. This
  preserves the same per-level parallelism, but now surfaces exceptions from
  triggerThread (e.g. an unresolved child_pipeline name) via
  stage.appendErrorMessage instead of the thread dying silently to stderr,
  and correctly restores the interrupt flag instead of swallowing it.
- Updated call sites and unit tests for the new addLevels signature; added
  regression tests for the new cycle-detection and unresolved-dependency
  error paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants