Skip to content

Lifecycle Logic

AQE exposes one trait per lifecycle phase:

aq-engine/src/core/lifecycle/mod.rs
pub trait OnStartLogic {
fn version(&self) -> &str;
fn run(&mut self, ctx: &mut dyn StrategyContext) -> LifecycleResult;
}
pub trait OnInitLogic {
fn version(&self) -> &str;
fn run(&mut self, ctx: &mut dyn StrategyContext, asset: &Asset) -> LifecycleResult;
}
pub trait OnTeardownLogic {
fn version(&self) -> &str;
fn run(&mut self, ctx: &mut dyn StrategyContext) -> LifecycleResult;
}

Each run method returns LifecycleResult, which records success, an optional message, and component metadata. A failed component with can_fail(false) stops the run; a failed component with can_fail(true) logs the failure and lets the run continue.

Default failure policy:

  • OnStartLogic: strict by default
  • OnInitLogic: strict by default
  • OnTeardownLogic: tolerant by default, because cleanup should continue where possible

Lifecycle wrappers use LifecycleTiming to choose where they run around the strategy method body:

LifecycleTiming::BeforeGenerated
LifecycleTiming::AfterGenerated

In generated AQS projects, “generated” means the method body generated from the graph. In hand-written AQE projects, it is the inline body you wrote in the Strategy implementation.

Use BeforeGenerated for validation, environment setup, state seeding, and dependencies that the strategy body expects. Use AfterGenerated for follow-up work, registration checks, and metadata that depends on the strategy body having run.

Direct AQE projects register lifecycle logic on StrategyState before starting the run. The engine calls the components automatically; user strategy code should not call lifecycle run helpers manually.

state.add_on_start_logic(
OnStartLogicBuilder::new(Box::new(SeedRuntimeState::new()))
.timing(LifecycleTiming::BeforeGenerated)
.can_fail(false)
.build(),
);
state.add_on_init_logic(
OnInitLogicBuilder::new(Box::new(InitAssetState::new()))
.timing(LifecycleTiming::AfterGenerated)
.can_fail(false)
.build(),
);
state.add_on_teardown_logic(
OnTeardownLogicBuilder::new(Box::new(FlushRuntimeLogs::new()))
.timing(LifecycleTiming::AfterGenerated)
.can_fail(true)
.build(),
);
use aq_engine::core::lifecycle::{LifecycleResult, OnStartLogic};
use aq_engine::core::strategy::StrategyContext;
use serde_json::json;
pub struct SeedRuntimeState;
impl SeedRuntimeState {
pub fn new() -> Self {
Self
}
}
impl OnStartLogic for SeedRuntimeState {
fn version(&self) -> &str {
"1.0"
}
fn run(&mut self, ctx: &mut dyn StrategyContext) -> LifecycleResult {
ctx.variables().insert(
self.name().to_string(),
json!({
"started": true,
"symbols_seen": 0
}),
);
LifecycleResult::passed(self.name().to_string())
}
}