Skip to content

Cache and message bus

VerifiedOwner Backend / platformLast verified backend@efa38e04e2db37a444e9f17100323c2ad4b83647 nautilus@2.0.0rc3

Nautilus's Cache and MessageBus are official, in-process components every LiveNode and BacktestNode uses internally. ONIX's runtime team runs a small set of standalone capability probes directly against the pinned wheel — not against documentation — before relying on any of this behavior, because a stub file can describe a Python surface that never actually round-trips. The results below are what those probes proved at nautilus-trader 2.0.0rc3, each reported with its evidence rather than assumed.

Cache save/load: reachable, but a proven no-op at this pin

LiveNodeBuilder.with_load_state(True) / with_save_state(True) are reachable from Python and do not raise. Upstream's own Trader::load_state/save_state are documented as no-ops unless the Cache has database backing. At this pin, the Python-exposed Cache object has no has_backing accessor at all, and CacheConfig's full public field list has no database/backing parameter of any kind. Both were confirmed by direct construction and introspection, not by reading the stub alone. Conclusion: cache save/load is callable, but on this pinned wheel it can only ever persist and restore nothing — it is not a usable restart/replay mechanism.

Redis / Postgres cache config: constructible, but not wired to anything

RedisCacheConfig, PostgresCacheConfig, and RedisMessageBusConfig changed between rc2 and rc3: at rc2 they were empty @typing.final stub classes that raised TypeError on construction; at rc3, all three construct successfully from Python with zero-argument defaults — confirmed by direct construction at this pin, not inferred from the earlier rc2 behavior. This proves the config objects are now reachable from Python. It does not prove an external Redis or Postgres backend is wired end to end: CacheConfig still has no field to accept one of these objects (the same check as above, same probe run), and no probe attempted to plug a constructed config into a live cache or message bus. Conclusion: external cache/message-bus backing is unreachable in practice at this pin, even though the configuration types themselves are now constructible — this improved between rc2 and rc3 but did not close the gap.

Event store: categorically unreachable from Python

Upstream's LiveNodeBuilder.with_event_store<F> is a Rust-generic method, never exposed to PyO3. The Python-facing LiveNodeConfig constructor has no event_store parameter at all and hardcodes event_store: None in the struct it builds regardless of what Python passes; LiveNodeBuilder's actual Python method list has no with_event_store at all. Conclusion: capture/seal/replay via Nautilus's Rust-side event store is real and wired into the kernel lifecycle in Rust, but is a total, categorical absence from this pinned Python wheel — not a partial surface.

MessageBus: the in-process bus works; external backing does not

A standalone nautilus_trader.common.MessageBus really does route an arbitrary Python object end to end through subscribe(topic, handler) / publish(topic, msg) — proven with a literal round-trip, not merely "the stub says so." MessageBus.has_backing is False both for a default-constructed bus and for one built with an explicit default MessageBusConfig(). Because RedisMessageBusConfig has the same unreachable-in-practice status as the cache configs above, external message-bus backing is unreachable the same way external cache backing is: only the in-process bus is usable at this pin.

What this means for ONIX

ONIX does not currently rely on Nautilus's cache save/load, event store, or any externally-backed message bus for durability or restart continuity — the proofs above are exactly why: none of them would currently do anything useful. Restart-safety for the pieces ONIX does need (hydration scheduling state, coverage accounting) is implemented as ONIX's own small, atomic, file-based persistence layered beside Nautilus's components (see ../data/catalog.md), not as a claim about a Nautilus-provided durability mechanism that this pin does not actually deliver.

Cross-process fanout: not a message-bus topology at all

Because external MessageBus backing is unreachable at this pin (proven above), ONIX does not, and cannot, cross a Redis- or Postgres-backed message bus between processes for market data or state fanout — there is no such topology active, hoped-for, or half-built in this repository at this pin. What actually crosses a process boundary is a different, simpler mechanism this documentation states plainly rather than leaving implied: spine.state.SpineState's in-process bounded-queue broadcast, fed to callers only via plain HTTP Server-Sent Events over the gateway's /stream/* and /v2/stream/* routes — see index.md's "Live market projection" section for the actor/state/SSE mechanics in full, including the ordering (sequence cursors) and recovery (event: resync) guarantees that fanout provides. If an earlier design used, or planned to use, a Redis-backed cross-process message-bus topology, no trace of it is wired up or reachable at this pin — this documentation retires that possibility explicitly rather than leaving a reader to infer it from silence, on the strength of the same probes that show RedisMessageBusConfig constructs but has nowhere to plug into.

Evidence and source pins for this page

Verified. Current behaviour, confirmed in source at the pinned commit.

Verified on against the following immutable sources:

  • backend@efa38e04:python/src/onix_engine/runtime/probes.py
  • backend@efa38e04:python/src/onix_engine/runtime/lifecycle.py

Status tokens are defined on the documentation and status model page. Every pin on this site is listed under versions and source pins.