Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Standard Library as Architecture

Most of Aikido’s important runtime structure is expressed with ordinary Rust types rather than framework machinery.

HashMap: dynamic identity and owned state

HashMap<String, ContractRuntimeState> means a deployment executor can discover contracts dynamically while retaining exactly one owned state record per normalized contract ID. HashMap::entry performs initialize-if-absent without duplicating lookup logic.

Source: ensure_contract_runtime

The same collection expresses different invariants elsewhere:

  • synthetic positions keyed by strategy, deployment, instrument, and lane;
  • router accounts and open positions keyed by normalized identity;
  • recently seen intent IDs keyed to time buckets for deduplication.

The key type is part of the architecture: it states what the system considers the same thing.

Arc: shared lifetime, not shared mutation

Arc<T> lets independently spawned tasks own the same long-lived service or shutdown flag. It does not make T mutable or thread-safe by itself.

Examples include Arc<AtomicBool> for shutdown and Arc<FleetGuardrails> for a shared service. The inner type still determines the mutation protocol.

Mutex and RwLock: snapshots with short critical sections

  • Arc<Mutex<StrategyRunner>> permits hot-reloadable strategy state while one engine evaluates it exclusively.
  • Arc<RwLock<RoutingSnapshot>> permits frequent read snapshots with rarer publication updates.
  • UI state uses Arc<Mutex<DeploymentState>> because it is shared display and operator state, not the account’s primary execution owner.

Poisoning is sometimes treated as fatal with expect or unwrap, and sometimes converted into anyhow::Error. That choice reveals whether corrupted shared state is considered recoverable at that boundary.

Atomics: independent facts

AtomicBool represents the monotonic request to shut down. Engine statistics use atomic counters because each metric is independently observable and does not require a consistent multi-field transaction.

An atomic would be a poor replacement for positions or a routing plan: those values have relationships that must change together.

Enums: closed command protocols

ExecutorCommand models every request the account owner understands, including signals, reconcile, flatten, converge, manual operations and shutdown. ExecutorStateUpdate models the smaller feedback protocol.

The compiler forces each exhaustive match to confront new variants. This is stronger than passing strings or loosely shaped JSON between in-process tasks.

Option and Result: absence versus failure

  • Option<&mut BrokerClient> means dry/deferred execution may legitimately have no active broker reference.
  • Result<T> means an attempted operation failed.
  • Option<oneshot::Sender<Result<(), String>>> means a command may optionally request a direct completion response.

Keeping these cases distinct prevents “not applicable,” “not yet connected,” and “failed” from collapsing into one ambiguous null or boolean.