Registry and Service
ForgeRegistry and ForgeService bridge compiled forge artifacts into the
frame lifecycle. The registry tracks lifecycle state for each artifact; the
service drives state transitions in response to frame hooks.
Lifecycle States
pub enum ForgeLifecycleState {
Pending,
Generating,
Compiled,
Registered,
Active,
}
States advance linearly in one direction only:
Pending -> Generating -> Compiled -> Registered -> Active
| State | Meaning |
|---|---|
Pending |
Registered but generators have not run yet |
Generating |
JTL generators are running or scheduled |
Compiled |
compile_forge() has completed; artifact is ready |
Registered |
Artifact registered with its frame service |
Active |
Fully live; participates in every frame |
Active is idempotent — calling advance_state() on an active record is a
no-op.
ForgeRecord
pub struct ForgeRecord<TCompiled> {
pub forge_id: String,
pub state: ForgeLifecycleState,
pub artifacts: TCompiled,
}
TCompiled is the domain-specific compiled artifact type (e.g.
CompiledRegionArtifacts). The record owns both the lifecycle state and the
artifact so they are always consistent.
// Create in Pending state
let record = ForgeRecord::new("my_region_id".to_string(), artifacts);
// Advance one step
record.advance_state()?; // Pending -> Generating
ForgeRegistry
pub struct ForgeRegistry<TCompiled> { /* BTreeMap<String, ForgeRecord<TCompiled>> */ }
Backed by a BTreeMap for deterministic iteration order (sorted by forge_id).
Key Methods
impl<TCompiled> ForgeRegistry<TCompiled> {
pub fn new() -> Self;
/// Register an artifact in Pending state.
pub fn register(&mut self, forge_id: String, artifacts: TCompiled);
/// Look up by forge id.
pub fn get(&self, forge_id: &str) -> Option<&ForgeRecord<TCompiled>>;
pub fn get_mut(&mut self, forge_id: &str) -> Option<&mut ForgeRecord<TCompiled>>;
/// Iterate all records in deterministic order.
pub fn iter(&self) -> impl Iterator<Item = &ForgeRecord<TCompiled>>;
/// Advance all records that are currently in `from_state`.
pub fn advance_all_from_state(&mut self, from_state: ForgeLifecycleState);
/// Count records in a given state.
pub fn count_by_state(&self, state: ForgeLifecycleState) -> usize;
}
Bulk Advance Pattern
The standard usage is to call advance_all_from_state once per frame phase
after the relevant work for that phase completes:
// After generators have run:
registry.advance_all_from_state(ForgeLifecycleState::Generating);
// After compile_forge calls have finished:
registry.advance_all_from_state(ForgeLifecycleState::Compiled);
ForgeService
ForgeService<TCompiled> implements plant_frame::ForgeService and drives the
registry through lifecycle states in response to frame hooks.
pub struct ForgeService<TCompiled> {
name: String, // display name for diagnostics
priority: u32, // dispatch priority within frame phase (default 50)
registry: Arc<RwLock<ForgeRegistry<TCompiled>>>,
}
The registry is wrapped in Arc<RwLock<>> so callers can hold a clone and
access it across async boundaries. ForgeService is itself Clone.
Construction
let service = ForgeService::new("RegionForgeService".to_string())
.with_priority(10);
// Access the registry from outside the service (e.g. during provision)
let registry_handle = service.registry();
Frame Hooks
ForgeService implements the ForgeService trait. During each frame phase it:
on_frame_init— advances allPendingrecords toGenerating(triggers generator scheduling on the next tick).on_frame_active— advances allGeneratingrecords that have completed throughCompiledandRegisteredtoActive.on_frame_aggregation— (currently a no-op; reserved for future drain logic).on_frame_cleanup— (currently a no-op; reserved for bookkeeping).
StateSnapshot
pub struct StateSnapshot {
pub pending: usize,
pub generating: usize,
pub compiled: usize,
pub registered: usize,
pub active: usize,
}
Call service.state_snapshot() at any time to observe the current distribution
of records across states. Useful for health checks and diagnostics endpoints.
let snap = service.state_snapshot();
println!("{} active, {} pending", snap.active, snap.pending);
Registration with FrameManager
Register your ForgeService with the FrameManager the same way as any
ForgeService:
frame_manager.register_service(Box::new(region_forge_service)).await?;
See Frame Manager Reference and ForgeService Trait Reference for the full registration lifecycle.