From 0e378402764124dd5f5eb849f1ec742f091d2a02 Mon Sep 17 00:00:00 2001 From: waynemwashuma <94756970+waynemwashuma@users.noreply.github.com> Date: Mon, 25 May 2026 22:49:38 +0300 Subject: [PATCH 1/3] Add schedule default system group configuration --- src/app/app.js | 2 +- src/schedule/core/executable.js | 9 ++++++++- src/schedule/core/systembuilder.js | 20 ++++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/app/app.js b/src/app/app.js index 0005643e..7c785f44 100644 --- a/src/app/app.js +++ b/src/app/app.js @@ -100,7 +100,7 @@ export class App { } /** - * @param {{label: string, delay?: number, repeat?: boolean, errorHandler?: (error: Error, world: World) => void}} config + * @param {{label: string, delay?: number, repeat?: boolean, errorHandler?: (error: Error, world: World) => void, defaultSystemGroup?: import('../type/index.js').Constructor}} config */ createSchedule(config) { return this.scheduler.set(new Executable(config)) diff --git a/src/schedule/core/executable.js b/src/schedule/core/executable.js index b40981f2..eb4b65d3 100644 --- a/src/schedule/core/executable.js +++ b/src/schedule/core/executable.js @@ -50,6 +50,12 @@ export class Executable { */ delay + /** + * @readonly + * @type {import('../../type/index.js').Constructor | undefined} + */ + defaultSystemGroup + /** * @readonly * @type {((error: Error, world: World) => void) | undefined} @@ -57,12 +63,13 @@ export class Executable { errorHandler /** - * @param {{label: string, repeat?: boolean, delay?: number, errorHandler?: (error: Error, world: World) => void}} config + * @param {{label: string, repeat?: boolean, delay?: number, errorHandler?: (error: Error, world: World) => void, defaultSystemGroup?: import('../../type/index.js').Constructor}} config */ constructor(config) { this.label = config.label this.repeat = config.repeat ?? true this.delay = config.delay ?? 0 this.errorHandler = config.errorHandler + this.defaultSystemGroup = config.defaultSystemGroup } } diff --git a/src/schedule/core/systembuilder.js b/src/schedule/core/systembuilder.js index 34d0b57e..03eb275b 100644 --- a/src/schedule/core/systembuilder.js +++ b/src/schedule/core/systembuilder.js @@ -37,7 +37,14 @@ export class SchedulerBuilder { * @param {Scheduler} scheduler */ pushToScheduler(scheduler) { - const schedules = this.createScheduleContexts() + /** @type {Map} */ + const defaultGroupsBySchedule = new Map() + + for (const executable of scheduler.values()) { + defaultGroupsBySchedule.set(executable.label, executable.defaultSystemGroup) + } + + const schedules = this.createScheduleContexts(defaultGroupsBySchedule) for (const [scheduleLabel, context] of schedules) { const schedule = scheduler.get(scheduleLabel) @@ -52,9 +59,10 @@ export class SchedulerBuilder { /** * @private + * @param {Map} defaultGroupsBySchedule * @returns {Map} */ - createScheduleContexts() { + createScheduleContexts(defaultGroupsBySchedule) { /** @type {Map} */ const schedules = new Map() @@ -115,11 +123,13 @@ export class SchedulerBuilder { } for (const [scheduleLabel, context] of schedules) { + context.defaultSystemGroup = defaultGroupsBySchedule.get(scheduleLabel) + this.resolveGroupParents(context, scheduleLabel) for (let i = 0; i < context.systems.length; i++) { const system = context.systems[i] - const groupLabel = system.config.systemGroup + const groupLabel = system.config.systemGroup ?? context.defaultSystemGroup if (!groupLabel) continue @@ -433,7 +443,8 @@ function getOrCreateScheduleContext(schedules, label) { systems: [], groups: [], nodesByLabel: new Map(), - groupIdsByTypeId: new Map() + groupIdsByTypeId: new Map(), + defaultSystemGroup: undefined }) schedules.set(label, created) @@ -463,6 +474,7 @@ const ScheduleNodeKind = Object.freeze({ * @property {SystemGroupRegistration[]} groups * @property {Map} nodesByLabel * @property {Map} groupIdsByTypeId + * @property {Constructor | undefined} defaultSystemGroup */ /** From fbc8afbd2f232b96b4008a6008d86d590573bc0f Mon Sep 17 00:00:00 2001 From: waynemwashuma <94756970+waynemwashuma@users.noreply.github.com> Date: Mon, 25 May 2026 22:51:22 +0300 Subject: [PATCH 2/3] Add tests for default schedule system groups --- src/schedule/tests/scheduleBuilder.test.js | 100 +++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/schedule/tests/scheduleBuilder.test.js b/src/schedule/tests/scheduleBuilder.test.js index 7bf15b25..a94836af 100644 --- a/src/schedule/tests/scheduleBuilder.test.js +++ b/src/schedule/tests/scheduleBuilder.test.js @@ -7,6 +7,9 @@ class Phase { } class ParentPhase { } class ChildPhase { } class MissingPhase { } +class DefaultPhase { } +class AlternatePhase { } +class FencePhase { } describe('Testing `SchedulerBuilder`', () => { test('sorts systems topologically from their `before` and `after` labels', () => { @@ -179,6 +182,103 @@ describe('Testing `SchedulerBuilder`', () => { deepStrictEqual(order, ['prepare', 'first', 'second', 'finish']) }) + test('uses the schedule default system group when a system omits one', () => { + const builder = new SchedulerBuilder() + const scheduler = new Scheduler() + const world = new World() + /** @type {string[]} */ + const order = [] + + function explicit() { order.push('explicit') } + function implicit() { order.push('implicit') } + function other() { order.push('other') } + + scheduler.set(new Executable({ + label: 'update', + defaultSystemGroup: DefaultPhase + })) + + builder.addGroup({ + label: DefaultPhase, + schedule: 'update', + before: [AlternatePhase] + }) + builder.addGroup({ + label: AlternatePhase, + schedule: 'update' + }) + builder.add({ + schedule: 'update', + systemGroup: DefaultPhase, + system: explicit + }) + builder.add({ + schedule: 'update', + system: implicit + }) + builder.add({ + schedule: 'update', + systemGroup: AlternatePhase, + system: other + }) + + builder.pushToScheduler(scheduler) + scheduler.get('update')?.run(world) + + deepStrictEqual(order, ['explicit', 'implicit', 'other']) + }) + + test('prefers an explicit system group over the schedule default', () => { + const builder = new SchedulerBuilder() + const scheduler = new Scheduler() + const world = new World() + /** @type {string[]} */ + const order = [] + + function explicit() { order.push('explicit') } + function implicit() { order.push('implicit') } + function fence() { order.push('fence') } + + scheduler.set(new Executable({ + label: 'update', + defaultSystemGroup: DefaultPhase + })) + + builder.addGroup({ + label: DefaultPhase, + schedule: 'update', + before: [FencePhase] + }) + builder.addGroup({ + label: AlternatePhase, + schedule: 'update', + after: [FencePhase] + }) + builder.addGroup({ + label: FencePhase, + schedule: 'update' + }) + builder.add({ + schedule: 'update', + system: implicit + }) + builder.add({ + schedule: 'update', + systemGroup: AlternatePhase, + system: explicit + }) + builder.add({ + schedule: 'update', + systemGroup: FencePhase, + system: fence + }) + + builder.pushToScheduler(scheduler) + scheduler.get('update')?.run(world) + + deepStrictEqual(order, ['implicit', 'fence', 'explicit']) + }) + test('orders groups relative to other groups', () => { const builder = new SchedulerBuilder() const scheduler = new Scheduler() From 56a9f073f25927a7843cb24ee132bb0028af955c Mon Sep 17 00:00:00 2001 From: waynemwashuma <94756970+waynemwashuma@users.noreply.github.com> Date: Mon, 25 May 2026 23:49:21 +0300 Subject: [PATCH 3/3] Lint files --- src/schedule/core/systembuilder.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/schedule/core/systembuilder.js b/src/schedule/core/systembuilder.js index 03eb275b..e64ea397 100644 --- a/src/schedule/core/systembuilder.js +++ b/src/schedule/core/systembuilder.js @@ -37,6 +37,7 @@ export class SchedulerBuilder { * @param {Scheduler} scheduler */ pushToScheduler(scheduler) { + /** @type {Map} */ const defaultGroupsBySchedule = new Map()