Small Bevy-adjacent persistence helpers for async key-value save/load workflows.
Use this crate when you have a blocking persistence backend and want to run its save/load work on Bevy task pools while your own app or plugin stays in control of when operations start, how results are handled, and when pending work is flushed.
Store<K, V>: a cloneable synchronous key-value backend trait.StoreBackend<K, V, B>: a Bevy component that holds a backend on an entity.PendingStoreOps<K, V>: a Bevy component that spawns save/load tasks, polls completions, and exposes completed loads plus load/save errors.PersistenceError: common persistence error variants for IO, serialization, deserialization, and version mismatches.FileSystemStore<V>: a JSON file-backedStore<String, V>for live app persistence.
This crate does not provide a Bevy Plugin today. There are no systems or resources to register globally; integrate the components from your own Bevy app or plugin. See the file_system_store example for a complete integration.
- Use
FileSystemStore<V>for JSON files, or implementStore<K, V>for a custom backend. - Spawn an entity with
StoreBackend::new(backend)andPendingStoreOps::<K, V>::default(). - In your systems, query both components, call
spawn_load/spawn_save, callpoll(), then draincompleted_loads,load_errors, andsave_errors. - For shutdown-critical writes, call
flush()before exiting.
spawn_load and spawn_save require Bevy's global async compute task pool to be initialized. Normal Bevy apps that install Bevy's task-pool setup satisfy this. Standalone tests/examples can initialize it explicitly with AsyncComputeTaskPool::get_or_init.
flush() waits for pending tasks to finish and surfaces their errors. It does not guarantee crash or power-loss durability; that depends on the backend.
FileSystemStore<V> stores one pretty JSON file per String key under a root directory. V must implement Serialize and DeserializeOwned.
Keys are restricted to simple file-name stems. Empty keys, absolute paths, path separators, parent-directory components, and multi-component paths are rejected so keys cannot escape the configured root directory.
Writes use a *.json.tmp file followed by rename. This is suitable as a small live-app backend, but it does not fsync files or directories, so production apps with strict crash-durability requirements should provide their own backend policy.
Check or run the example backend:
cargo check --examples
cargo run --example file_system_storeexamples/file_system_store.rs demonstrates the public FileSystemStore, missing-file handling, and async load usage.
Store::saveandStore::loadmay block;PendingStoreOpsruns them on Bevy's async compute task pool.- Load and save results are recorded in completion order.
- Operations for the same key are not ordered, deduplicated, retried, or merged.
- Callers own draining result/error vectors.
- Load errors and save errors are caller-visible. This intentionally differs from the source extraction, where save errors were logged only.
FileSystemStoredoes not provide encryption, access control, secure deletion, retention policy, or safe handling for secrets/PII. Production apps must choose appropriate storage locations, permissions, encryption/key management, and logging behavior.
cargo test
cargo check --examples