Expand description
§ai-store-sync
Blocking (synchronous) facade over ai_store_core::Store.
§Why
Store is async by design; the SPI traits (EventBackend, CacheBackend,
ProjectionSink) are async_trait. Consumers embedded in an otherwise
synchronous codebase would otherwise have to spin up a tokio::Runtime and
wrap every call in runtime.block_on(...), and get the details right
(current-thread vs multi-thread, runtime lifetime, Send bounds).
BlockingStore does that once, in-tree.
§Choosing a constructor
BlockingStore::new— owns a dedicatedcurrent_threadruntime. Use this from a plain synchronousmain/ thread when the caller has no tokio runtime of its own. Analogous toreqwest::blocking::Client::new.BlockingStore::with_handle— borrows an existingtokio::runtime::Handle. Use this when the surrounding process already runs a runtime (e.g. a library that hosts tokio internally and hands aHandledown to sync plugin code).
§Nested-runtime pitfall
Do not call a BlockingStore method from inside an async task on the
same tokio runtime — that would attempt to block_on from within a runtime
worker and will panic. If you must bridge from async code:
- prefer calling
Storedirectly with.await, or - wrap the blocking call in
tokio::task::block_in_placeon a multi-thread runtime.
§Errors
All methods return StoreError verbatim from the async facade. No new
error variants are introduced.
Structs§
- Blocking
Sink - Adapter turning a
SyncProjectionSinkinto aProjectionSink. - Blocking
Store - Synchronous mirror of
Store.
Enums§
- Dispatch
- How
BlockingSinkhands off calls to the wrappedSyncProjectionSink.
Traits§
- Sync
Projection Sink - Synchronous variant of
ProjectionSink. Implement this when the sink’s body is inherently blocking (file I/O, synchronous database drivers, stdlibprintln!), then wrap inBlockingSinkto plug into the async facade.