Setup Lifecycle and Async Coordination
Aircada provides robust lifecycle hooks via @Setup that support asynchronous execution, topological dependency sorting, and cross-stage waiting mechanisms. These guarantee that asynchronous setup tasks (like resource loading, fetching option rows, or computing positions) execute in the correct order before subsequent system transitions occur.
Asynchronous Lifecycle Stages
The @Setup decorator accepts a stage parameter. Lifecycle stages execute sequentially in the following order: bootstrap -> initialize -> finalize -> runtime. Within a stage, methods run concurrently unless execution constraints are declared.
Topological Dependency Sorting
You can declare dependency constraints using after and before configurations. The Aircada scheduler runs a topological sort to guarantee the correct execution sequence, even with variable async task durations.
Cross-Stage Async Waiting
For complex, heavy loading (like asynchronously fetching models or configs in the background), you can trigger an unawaited background promise in an early stage (like initialize) to keep the startup process non-blocking, and then await its resolution in a later stage (like finalize) before runtime execution starts.
import { Operator, Setup } from '@aircada/spec';
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
@Operator({
name: 'NormalStageOperator',
type: 'normal_stage_operator'
})
export class NormalStageOperator {
private pendingPromise?: Promise<void>;
@Setup({ stage: 'bootstrap' })
async setupBootstrap() {
await delay(50);
console.log('Bootstrap stage setup complete.');
}
@Setup({ stage: 'initialize' })
setupInitialize() {
// Spawn an unawaited background task to prevent blocking initialize
this.pendingPromise = (async () => {
await delay(150);
console.log('Background initialization complete.');
})();
}
@Setup({ stage: 'finalize' })
async setupFinalize() {
// Wait for the background task to complete before entering runtime stage
if (this.pendingPromise) {
await this.pendingPromise;
}
console.log('Finalize stage setup complete.');
}
@Setup({ stage: 'runtime' })
async setupRuntime() {
await delay(120);
console.log('Runtime stage setup complete.');
}
}import { Operator, Setup } from '@aircada/spec';
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
@Operator({
name: 'TopoA',
type: 'topo_a'
})
export class TopoA {
@Setup({ stage: 'initialize' })
async setupA() {
await delay(100);
console.log('TopoA setup completed.');
}
}
@Operator({
name: 'TopoB',
type: 'topo_b'
})
export class TopoB {
// Runs in initialize stage, but only AFTER TopoA has finished setup
@Setup({ stage: 'initialize', after: 'TopoA' })
async setupB() {
await delay(150);
console.log('TopoB setup completed.');
}
}
@Operator({
name: 'TopoC',
type: 'topo_c'
})
export class TopoC {
// Runs in initialize stage, but must complete BEFORE TopoB starts setup
@Setup({ stage: 'initialize', before: 'TopoB' })
async setupC() {
await delay(50);
console.log('TopoC setup completed.');
}
}About the Author
Wylie Chenoweth is the CTO of Aircada. He leads the engineering team building the high-performance 3D rendering engine and tools, bringing over a decade of systems architecture and 3D web rendering experience.






