콘텐츠로 이동

수명 주기 로직

AQE는 수명 주기 단계마다 하나의 트레이트를 제공합니다.

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;
}

각 run 메서드는 성공 여부, 선택적 메시지, 컴포넌트 메타데이터를 기록하는 LifecycleResult를 반환합니다. can_fail(false)인 컴포넌트가 실패하면 실행이 중단됩니다. can_fail(true)인 컴포넌트가 실패하면 실패를 기록하고 실행을 계속합니다.

기본 실패 정책은 다음과 같습니다.

  • OnStartLogic: 기본적으로 실패 시 실행 중단
  • OnInitLogic: 기본적으로 실패 시 실행 중단
  • OnTeardownLogic: 가능한 한 정리를 계속해야 하므로 기본적으로 실패해도 실행 계속

수명 주기 래퍼는 LifecycleTiming을 사용해 전략 메서드 본문의 앞뒤 중 어느 위치에서 실행할지 선택합니다.

LifecycleTiming::BeforeGenerated
LifecycleTiming::AfterGenerated

생성된 AQS 프로젝트에서 “generated”는 그래프에서 생성한 메서드 본문을 뜻합니다. 직접 작성한 AQE 프로젝트에서는 Strategy 구현에 작성한 인라인 본문을 뜻합니다.

검증, 환경 설정, 초기 상태 설정, 전략 본문이 필요로 하는 의존성에는 BeforeGenerated를 사용하세요. 후속 작업, 등록 검사, 전략 본문 실행이 끝나야 얻을 수 있는 메타데이터에는 AfterGenerated를 사용하세요.

AQE를 직접 사용하는 프로젝트는 실행을 시작하기 전에 StrategyState에 수명 주기 로직을 등록합니다. 엔진이 컴포넌트를 자동으로 호출하므로, 사용자 전략 코드에서 수명 주기 실행 헬퍼를 수동으로 호출해서는 안 됩니다.

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())
}
}