Skip to content

Commit

Permalink
Merge pull request #245 from proto-kit/fix/resolve-sequencer-ordering
Browse files Browse the repository at this point in the history
Record resolving order in the sequencer and start modules based on that
  • Loading branch information
ejMina226 authored Dec 13, 2024
2 parents 6225088 + ce40647 commit 2d5ca04
Showing 1 changed file with 36 additions and 2 deletions.
38 changes: 36 additions & 2 deletions packages/sequencer/src/sequencer/executor/Sequencer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ export class Sequencer<Modules extends SequencerModulesRecord>
* modules to start each
*/
public async start() {
// The sequencer uses tsyringe to resolve modules (and their dependencies)
// and then starts them. However, this can be problematic as although tsyringe may resolve
// dependencies, it doesn't actually start them. For example, a database may be created,
// but the connection strings, etc, won't be constructed until it's started, and this may
// cause an error if a module that relies on it is started first. The way to fix this is
// ensure that we start modules based on the order they were resolved.
// We iterate through the methods three times:

this.useDependencyFactory(this.container.resolve(MethodIdFactory));

// Log startup info
Expand All @@ -75,15 +83,41 @@ export class Sequencer<Modules extends SequencerModulesRecord>
log.info("Starting sequencer...");
log.info("Modules:", moduleClassNames);

// Iteration #1: We invoke the afterResolution feature for the container
// to ensure every time a module is resolved it gets recorded.
const orderedModules: Extract<keyof Modules, string>[] = [];
// eslint-disable-next-line guard-for-in
for (const moduleName in this.definition.modules) {
this.container.afterResolution(
moduleName,
() => {
orderedModules.push(moduleName);
},
{
frequency: "Once",
}
);
}
// Iteration #2: We resolve each module and thus populate
// the orderedModules list to understand the sequencing.
// eslint-disable-next-line guard-for-in
for (const moduleName in this.definition.modules) {
const sequencerModule = this.resolve(moduleName);

log.info(
`Starting sequencer module ${moduleName} (${sequencerModule.constructor.name})`
`Resolving sequencer module ${moduleName} (${sequencerModule.constructor.name})`
);
}

// Iteration #3: We now iterate though the orderedModules list
// and start the modules in the order they were resolved.
for (const moduleName of orderedModules) {
const sequencerModule = this.resolve(moduleName);
// eslint-disable-next-line no-await-in-loop
await sequencerModule.start();

log.info(
`Starting sequencer module ${moduleName} (${sequencerModule.constructor.name})`
);
}
}
}

0 comments on commit 2d5ca04

Please sign in to comment.