Module Events
Delivery reliability, timing guarantees, and integration patterns for the module event system. For the full event type catalog and subscription API, see Module system. For maintenance event payloads, see Janitorial events.
Event timing
Event types follow fixed timing so modules subscribe before receiving ModuleLoaded.
ModuleLoaded
ModuleLoaded events are only published after a module has subscribed (startup complete).
Flow:
- Module process is spawned
- Module connects via IPC and sends Handshake
- Module sends
SubscribeEvents - At subscription time:
- Module receives
ModuleLoadedfor all already-loaded modules ModuleLoadedis published for the newly subscribing module (if loaded)
- Module receives
- Module is operational
Why: subscription completes before ModuleLoaded, so hotloaded modules receive existing modules and ordering is always subscription → ModuleLoaded.
Startup (Module A first): spawn → connect → subscribe → ModuleLoaded for A.
Hotload (Module B later): B subscribes → receives ModuleLoaded for A → ModuleLoaded published for B.
DataMaintenance
Single event for flush/cleanup (replaces StorageFlush and DataCleanup).
Payload: operation (flush, cleanup, both), urgency (low, medium, high), reason, optional target_age_days, optional timeout_seconds.
#![allow(unused)] fn main() { // Shutdown flush DataMaintenance { operation: "flush", urgency: "high", reason: "shutdown", timeout_seconds: Some(5) } // Periodic cleanup DataMaintenance { operation: "cleanup", urgency: "low", reason: "periodic", target_age_days: Some(30) } }
Migration from old events:
#![allow(unused)] fn main() { // Old: separate StorageFlush / DataCleanup handlers // New: one DataMaintenance handler keyed on operation + urgency match event_type { EventType::DataMaintenance => { if let EventPayload::DataMaintenance { operation, .. } = payload { if operation == "flush" || operation == "both" { flush_data().await?; } if operation == "cleanup" || operation == "both" { cleanup_data().await?; } } } _ => {} } }
Delivery and backpressure
Reliability model
- At-most-once per subscriber; full channel drops the event (no retry)
- Best-effort — slow or dead modules may miss events; statistics track success/failure
- Per-module ordering on a single channel; no cross-module ordering guarantee
Channel behavior
- Buffer: 100 events per module (hardcoded today)
- Non-blocking publish:
try_send; publisher never blocks - Channel full: event dropped with warning; subscription kept (module is slow, not dead)
- Channel closed: subscription removed (module dead)
#![allow(unused)] fn main() { let stats = event_manager.get_delivery_stats("module_id").await; // Option<(successful_deliveries, failed_deliveries, channel_full_count)> }
Hotload and missed events
Newly subscribing modules receive ModuleLoaded for all already-loaded modules so late starters get a consistent view without replaying the full event log.
Event categories (summary)
Full enum lists and subscription examples: Module system → Event System.
| Category | Examples |
|---|---|
| Blockchain | NewBlock, NewTransaction, BlockDisconnected, ChainReorg |
| Governance | GovernanceProposalCreated, GovernanceProposalVoted, GovernanceProposalMerged, GovernanceForkDetected |
| Network | PeerConnected, PeerDisconnected, PeerBanned, MessageReceived |
| Module lifecycle | ModuleLoaded, ModuleUnloaded, ModuleCrashed, ModuleHealthChanged |
| Maintenance | DataMaintenance, MaintenanceStarted, MaintenanceCompleted, HealthCheck |
| Resources | DiskSpaceLow, ResourceLimitWarning |
| Node lifecycle | NodeStartupCompleted, NodeShutdown, NodeShutdownCompleted |
Monitoring
#![allow(unused)] fn main() { let stats = event_manager.get_delivery_stats("module_id").await; let all_stats = event_manager.get_all_delivery_stats().await; let subscribers = event_manager.get_subscribers(EventType::NewBlock).await; event_manager.reset_delivery_stats("module_id").await; // testing }
Module developer checklist
- Subscribe immediately after handshake
- Handle
ModuleLoadedto discover peer modules - Keep handlers non-blocking
- Handle
NodeShutdownand high-urgencyDataMaintenance - Monitor delivery statistics if events seem missing
Node developer checklist
- Publish through
EventPublisherat stable code points - Log delivery warnings
- Watch per-module channel-full counts for slow consumers
- Cover startup, hotload, and slow-module paths in integration tests
Extending events
- Add variants to
EventTypeandEventPayload - Add publisher helpers on
EventPublisher - Follow existing patterns (e.g.
DataMaintenancefor maintenance)
See Also
- Module system (design) — IPC, lifecycle, event catalog
- Janitorial events — maintenance event payloads
- Module IPC Protocol — wire protocol