#[non_exhaustive]pub struct Config {Show 28 fields
pub resp_listener: Option<SocketAddr>,
pub maxmemory: u64,
pub eviction_policy: EvictionPolicy,
pub data_dir: Option<PathBuf>,
pub aof: bool,
pub appendfsync: AppendFsync,
pub tier_budget: Option<TierBudgetSpec>,
pub max_spill_value: u64,
pub ttl_reaper: TtlReaperMode,
pub reaper_interval: Duration,
pub reaper_samples: usize,
pub reaper_max_rounds: u32,
pub auto_aof_rewrite_pct: u32,
pub auto_aof_rewrite_min_size: u64,
pub auto_aof_rewrite_bytes: u64,
pub auto_aof_rewrite_interval_secs: u64,
pub replay_mode: ReplayMode,
pub stage_bytes: u64,
pub mapped_aof: bool,
pub shards: usize,
pub replica_upstream: Option<String>,
pub replica_id: String,
pub replica_reconnect_min: Duration,
pub replica_reconnect_max: Duration,
pub embed_writer_listen_addr: Option<String>,
pub feed_enabled: bool,
pub feed_buffer_size: u64,
pub embed_writer_backlog_bytes: usize,
/* private fields */
}Expand description
Embedded-store config. Build by chaining with_* methods on
Config::default, or assign its public fields.
use kevy_embedded::{Config, Store};
let mut cfg = Config::default().with_ttl_reaper_manual();
cfg.reaper_samples = 40;
let store = Store::open(cfg)?;Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.resp_listener: Option<SocketAddr>Optional READ-ONLY RESP listener address (ops tooling —
redis-cli against a live embedded store). None (default) =
no listener thread, no socket, zero tax.
let addr: std::net::SocketAddr = "127.0.0.1:6009".parse()?;
assert_eq!(kevy_embedded::Config::default().resp_listener, None);
let cfg = kevy_embedded::Config::default().with_resp_listener(addr);
assert_eq!(cfg.resp_listener, Some(addr));maxmemory: u64Soft memory ceiling in bytes. 0 (default) = unlimited.
let cfg = kevy_embedded::Config::default().with_max_memory(64 << 20);
assert_eq!(cfg.maxmemory, 64 << 20);
assert_eq!(kevy_embedded::Config::default().maxmemory, 0); // unlimitedeviction_policy: EvictionPolicyEviction policy when over maxmemory. Default NoEviction.
use kevy_embedded::{Config, EvictionPolicy, Store};
let cfg = Config::default()
.with_max_memory(256 << 10)
.with_eviction(EvictionPolicy::AllKeysLru);
assert_eq!(cfg.eviction_policy, EvictionPolicy::AllKeysLru);
let s = Store::open(cfg)?;
for i in 0..2000 {
s.set(format!("k{i}").as_bytes(), &[0u8; 512])?;
}
assert!(s.info().evictions > 0, "old keys made room for new ones");data_dir: Option<PathBuf>Persistence directory. None = pure in-memory (no AOF, no snapshot).
use kevy_embedded::{Config, Store};
let dir = kevy_tmpdir::TmpDir::new("config-data-dir");
let cfg = Config::default().with_persist(dir.path());
assert_eq!(cfg.data_dir.as_deref(), Some(dir.path()));
Store::open(cfg.clone())?.set(b"k", b"v")?;
assert_eq!(Store::open(cfg)?.get(b"k")?.as_deref(), Some(&b"v"[..]));aof: boolAOF on/off when data_dir is set. Defaults to true (on) when
with_persist was called; ignored if data_dir is None.
use kevy_embedded::{Config, Store};
let dir = kevy_tmpdir::TmpDir::new("config-aof");
let cfg = Config::default().with_persist(dir.path()).without_aof();
assert!(!cfg.aof);
let s = Store::open(cfg)?;
s.set(b"k", b"v")?;
assert_eq!(s.info().aof_bytes, 0); // nothing is loggedappendfsync: AppendFsyncAOF fsync policy. Default EverySec (matches Redis: ≤ 1 s loss).
use kevy_embedded::{AppendFsync, Config};
assert_eq!(Config::default().appendfsync, AppendFsync::EverySec);
let cfg = Config::default().with_appendfsync(AppendFsync::Always);
assert_eq!(cfg.appendfsync, AppendFsync::Always);tier_budget: Option<TierBudgetSpec>Transparent-tiering RAM budget (capacity arc). None (default)
= tiering off — today’s paths byte-identical. Some requires a
disk data_dir (the cold value log lives at <data_dir>/tier/);
a mem-only store rejects the combo at open. The budget is the
WHOLE store’s (split evenly across shards); auto/percent forms
resolve against the detected memory bound at open and re-resolve
on every reaper tick.
use kevy_embedded::Config;
assert!(Config::default().tier_budget.is_none()); // tiering off
let cfg = Config::default().with_tier_budget(64 << 20);
assert!(cfg.tier_budget.is_some());max_spill_value: u64Largest value the tier may spill (bytes; 0 = unlimited). Default 256 KiB (RFC §7): an embedded cold read holds the shard lock for the pread, so the cap bounds that hold time. Over-cap values simply stay hot.
let mut cfg = kevy_embedded::Config::default();
assert_eq!(cfg.max_spill_value, 256 << 10);
cfg.max_spill_value = 0; // any value may spill
assert_eq!(cfg.max_spill_value, 0);ttl_reaper: TtlReaperModeTTL reaper mode. Default Background.
use kevy_embedded::{Config, Store, TtlReaperMode};
let cfg = Config::default().with_ttl_reaper_manual();
assert_eq!(cfg.ttl_reaper, TtlReaperMode::Manual);
let s = Store::open(cfg)?;
s.tick(); // the caller drives the reaperreaper_interval: DurationReaper tick interval. Default 100 ms (10 Hz).
use std::time::Duration;
let cfg = kevy_embedded::Config::default().with_reaper_interval(Duration::from_millis(10));
assert_eq!(cfg.reaper_interval, Duration::from_millis(10));reaper_samples: usizetick_expire samples per round. Default 20 (matches Redis).
let mut cfg = kevy_embedded::Config::default();
assert_eq!(cfg.reaper_samples, 20);
cfg.reaper_samples = 100; // reap harder per round
assert_eq!(cfg.reaper_samples, 100);reaper_max_rounds: u32Max sample rounds per tick. Default 16.
let mut cfg = kevy_embedded::Config::default();
assert_eq!(cfg.reaper_max_rounds, 16);
cfg.reaper_max_rounds = 4; // bound each tick's work
assert_eq!(cfg.reaper_max_rounds, 4);auto_aof_rewrite_pct: u32Auto-BGREWRITEAOF trigger: rewrite when the live AOF has grown by at
least this percent over its size at the previous rewrite. 0 disables
(call crate::Store::rewrite_aof manually). Default 100 (Redis).
let cfg = kevy_embedded::Config::default().with_auto_aof_rewrite(50, 1 << 20);
assert_eq!((cfg.auto_aof_rewrite_pct, cfg.auto_aof_rewrite_min_size), (50, 1 << 20));
assert_eq!(kevy_embedded::Config::default().auto_aof_rewrite_pct, 100);auto_aof_rewrite_min_size: u64Floor below which auto-rewrite is skipped. Default 64 MiB (Redis).
let cfg = kevy_embedded::Config::default();
assert_eq!(cfg.auto_aof_rewrite_min_size, 64 << 20);
let cfg = cfg.with_auto_aof_rewrite(100, 8 << 20);
assert_eq!(cfg.auto_aof_rewrite_min_size, 8 << 20);auto_aof_rewrite_bytes: u64Absolute-size auto-rewrite trigger in bytes (0 = off). The growth rule alone lets a large log double before compacting — a 2.2 GB AOF waits for 4.4 GB; this caps it outright.
let mut cfg = kevy_embedded::Config::default();
assert_eq!(cfg.auto_aof_rewrite_bytes, 0); // off
cfg.auto_aof_rewrite_bytes = 1 << 30; // compact once the log reaches 1 GiB
assert_eq!(cfg.auto_aof_rewrite_bytes, 1 << 30);auto_aof_rewrite_interval_secs: u64Time-based auto-rewrite trigger in seconds (0 = off): compact at least this often while the log grows.
let mut cfg = kevy_embedded::Config::default();
assert_eq!(cfg.auto_aof_rewrite_interval_secs, 0); // off
cfg.auto_aof_rewrite_interval_secs = 3600; // compact at least hourly
assert_eq!(cfg.auto_aof_rewrite_interval_secs, 3600);replay_mode: ReplayModeWhat replay does at a corrupt v2 record: stop there
(ReplayMode::Strict, the default), or hop to the next valid
record (length + CRC + parse all agree) instead of dropping the
good tail behind it (ReplayMode::Resync).
use kevy_embedded::{Config, ReplayMode};
assert_eq!(Config::default().replay_mode, ReplayMode::Strict);
let cfg = Config::default().with_replay_mode(ReplayMode::Resync);
assert_eq!(cfg.replay_mode, ReplayMode::Resync);stage_bytes: u64Size in bytes of each shard’s staging ring (0 = off): appends land
in a shared file mapping, so a process that is killed keeps every
write that returned. Only EverySec and No stage. Default 4 MiB.
let cfg = kevy_embedded::Config::default();
assert_eq!(cfg.stage_bytes, 4 << 20);
assert_eq!(cfg.with_stage_ring(0).stage_bytes, 0); // staging offmapped_aof: boolAppend by copying into a mapping of the AOF’s preallocated tail
instead of write(), under EverySec and No. It keeps a killed
process’s writes as the staging ring does, and replaces it. On by
default on Apple platforms only, where a fresh mapped page is cheap;
on Linux the page fault makes it slower than write().
let cfg = kevy_embedded::Config::default();
assert_eq!(cfg.mapped_aof, cfg!(target_vendor = "apple"));
assert!(!cfg.with_mapped_aof(false).mapped_aof);shards: usizeKeyspace shard count (hash(key) % shards), each a fully independent
lock + keyspace + AOF (shared-nothing) — concurrent access scales across
cores. Default 1 (single shard = the original single-lock /
single-aof-0.aof layout, zero migration). Set > 1 via
Self::with_shards; the first open with > 1 re-shards an existing
single AOF into per-shard files.
use kevy_embedded::{Config, Store};
assert_eq!(Config::default().with_shards(0).shards, 1); // clamped
let s = Store::open(Config::default().with_shards(4))?;
s.set(b"a", b"1")?;
s.set(b"b", b"2")?;
assert_eq!(s.info().keys, 2); // counted across all four shardsreplica_upstream: Option<String>Replication upstream. Some("host:port") makes this store a
read-replica that streams writes from the named primary; None
(default) is a normal primary store. Configured via
Self::with_replica_upstream or the convenience constructor
crate::Store::open_replica.
let cfg = kevy_embedded::Config::default().with_replica_upstream("10.0.0.5:6380");
assert_eq!(cfg.replica_upstream.as_deref(), Some("10.0.0.5:6380"));
assert!(kevy_embedded::Config::default().replica_upstream.is_none());replica_id: StringReplica identity string sent to the primary at handshake
(REPLICATE FROM <offset> ID <replica_id>). Default
"kevy-embedded-replica". Override per-process when multiple
embed replicas connect to the same primary (they’d otherwise
share the slot and clobber each other’s session state on the
primary side).
let cfg = kevy_embedded::Config::default();
assert_eq!(cfg.replica_id, "kevy-embedded-replica");
assert_eq!(cfg.with_replica_id("edge-7").replica_id, "edge-7");replica_reconnect_min: DurationReplica reconnect backoff: lower bound. Default 100 ms. The
runner sleeps this long after the first connection failure;
each subsequent failure doubles the wait up to
Self::replica_reconnect_max.
use std::time::Duration;
let cfg = kevy_embedded::Config::default()
.with_replica_reconnect(Duration::from_millis(50), Duration::from_secs(2));
assert_eq!(cfg.replica_reconnect_min, Duration::from_millis(50));replica_reconnect_max: DurationReplica reconnect backoff: upper bound. Default 5 s — matches the server-side replica reconnect default so embed replicas and server replicas behave identically when the same primary disappears.
use std::time::Duration;
let min = Duration::from_secs(1);
let cfg = kevy_embedded::Config::default().with_replica_reconnect(min, Duration::from_millis(10));
assert_eq!(cfg.replica_reconnect_max, min); // never below the lower boundembed_writer_listen_addr: Option<String>Embed-as-writer bind address ("host:port" or
"0.0.0.0:port") for the replication source listener. When
Some, every commit on this store pushes its argv into a
process-local ReplicationSource backlog, and replicas (other
embeds, server-as-replicas) connect to this port to stream the
writes. None (default) keeps the embed in pure-local mode.
Mutually exclusive in spirit with replica_upstream (a single
store should be either a writer source or a reader sink, not
both); the builder does not reject the combo so tests can
exercise the guard rails.
let cfg = kevy_embedded::Config::default().with_embed_writer("127.0.0.1:6390");
assert_eq!(cfg.embed_writer_listen_addr.as_deref(), Some("127.0.0.1:6390"));
assert!(kevy_embedded::Config::default().embed_writer_listen_addr.is_none());feed_enabled: boolCDC feed (changes_since / changes_tail). Default off.
use kevy_embedded::{Config, Store};
let cfg = Config::default().with_feed(0);
assert!(cfg.feed_enabled);
let s = Store::open(cfg)?;
assert!(s.changes_tail().is_ok()); // a disabled feed answers Disabledfeed_buffer_size: u64Feed backlog byte budget. Default 64 MB, capped at 1 GB.
let cfg = kevy_embedded::Config::default().with_feed(0);
assert_eq!(cfg.feed_buffer_size, 64 << 20);
let cfg = kevy_embedded::Config::default().with_feed(4 << 30);
assert_eq!(cfg.feed_buffer_size, 1 << 30); // capped at 1 GBembed_writer_backlog_bytes: usizeBacklog byte budget for the embed-as-writer source. Default
1 MiB (matches the server replication default).
Set higher when consumers may disconnect for longer than
the backlog can buffer (otherwise a reconnect falls past the
backlog and is re-seeded with a full snapshot ship instead of
an incremental stream).
let cfg = kevy_embedded::Config::default();
assert_eq!(cfg.embed_writer_backlog_bytes, 1 << 20);
assert_eq!(cfg.with_embed_writer_backlog(1).embed_writer_backlog_bytes, 64 << 10); // floorImplementations§
Source§impl Config
impl Config
Sourcepub fn with_resp_listener(self, addr: SocketAddr) -> Self
pub fn with_resp_listener(self, addr: SocketAddr) -> Self
Enable the read-only RESP listener on addr
(e.g. "127.0.0.1:6009".parse().unwrap()).
Sourcepub fn with_persist(self, dir: impl Into<PathBuf>) -> Self
pub fn with_persist(self, dir: impl Into<PathBuf>) -> Self
Enable persistence under dir — snapshot file + AOF land inside.
AOF defaults on; turn it off with Self::without_aof for pure
snapshot-only durability.
Sourcepub fn without_aof(self) -> Self
pub fn without_aof(self) -> Self
Disable the AOF (snapshot-only persistence — explicit save_snapshot
calls are the only way data survives restart).
Sourcepub fn with_max_memory(self, bytes: u64) -> Self
pub fn with_max_memory(self, bytes: u64) -> Self
Soft memory ceiling in bytes. 0 keeps the default (unlimited).
Sourcepub fn with_eviction(self, policy: EvictionPolicy) -> Self
pub fn with_eviction(self, policy: EvictionPolicy) -> Self
Eviction policy when over Self::with_max_memory.
Sourcepub fn with_appendfsync(self, fsync: AppendFsync) -> Self
pub fn with_appendfsync(self, fsync: AppendFsync) -> Self
AOF fsync policy. Default AppendFsync::EverySec.
Sourcepub fn with_auto_rewrite_bytes(self, bytes: u64) -> Self
pub fn with_auto_rewrite_bytes(self, bytes: u64) -> Self
Absolute-size auto-rewrite trigger: compact whenever the AOF reaches
bytes, regardless of growth ratio (0 = off). Complements
Self::with_auto_aof_rewrite, whose growth rule is too sluggish
for long-lived instances with a large baseline.
Sourcepub fn with_auto_rewrite_interval(self, interval: Duration) -> Self
pub fn with_auto_rewrite_interval(self, interval: Duration) -> Self
Time-based auto-rewrite trigger: compact at least every interval
while the log grows (zero duration = off).
Sourcepub fn with_auto_aof_rewrite(self, pct: u32, min_size: u64) -> Self
pub fn with_auto_aof_rewrite(self, pct: u32, min_size: u64) -> Self
Auto-BGREWRITEAOF thresholds: rewrite once the AOF has grown pct
percent past its size at the last rewrite AND is at least min_size
bytes. In Background reaper mode the check runs on the reaper tick;
in Manual mode it runs when you call crate::Store::tick. Pass
pct = 0 to disable auto-rewrite (you can still call
crate::Store::rewrite_aof yourself). Defaults: 100 % / 64 MiB.
Sourcepub fn with_auto_aof_rewrite_disabled(self) -> Self
pub fn with_auto_aof_rewrite_disabled(self) -> Self
Disable every automatic rewrite trigger — growth, absolute size
and interval — in one named call This is
the canary-window switch: the first rewrite is the documented
one-way step that upgrades a 3.x-era AOF to v2
(crate::Store::downgradeable_to_v3 reads the window), so an
embedder keeping a binary-swap escape hatch open turns the
automatics off rather than remembering which of three knobs
zeroes which rule. Explicit crate::Store::rewrite_aof calls
still work — and still close the window.
Sourcepub fn with_shards(self, n: usize) -> Self
pub fn with_shards(self, n: usize) -> Self
Shard the keyspace into n shared-nothing partitions (hash(key) % n),
each with its own lock + keyspace + AOF, so concurrent access scales
across cores. n clamps to ≥ 1; 1 (default) is the original
single-shard layout. Going from a single-AOF store to n > 1
re-shards the existing aof-0.aof into aof-0..aof-{n-1} on the next
open (the old file is backed up to aof-0.aof.premigration.<ts> first).
Pub/sub is process-wide (handled on shard 0), not sharded.
Sourcepub fn with_metric_sink(
self,
sink: impl Fn(KevyMetric) + Send + Sync + 'static,
) -> Self
pub fn with_metric_sink( self, sink: impl Fn(KevyMetric) + Send + Sync + 'static, ) -> Self
Register a push-style metric callback. It receives a crate::KevyMetric for
each AOF replay (startup) and AOF rewrite (compaction) — wire it to
Prometheus / a log line / a counter. The callback runs synchronously on
the emitting thread (reaper thread for background rewrites), so keep it
fast and non-blocking. Replaces any previously-set sink.
Sourcepub fn with_ttl_reaper_manual(self) -> Self
pub fn with_ttl_reaper_manual(self) -> Self
Caller-driven TTL reaping — disables the background thread.
Required for WASM (no threads available). Call
crate::Store::tick yourself from your event loop.
Sourcepub fn with_replica_upstream(self, upstream: impl Into<String>) -> Self
pub fn with_replica_upstream(self, upstream: impl Into<String>) -> Self
Configure this store as a replication replica of upstream
("host:port" of a kevy server’s replication listener). A
background thread streams writes from the primary and applies
them locally; this store rejects local writes with a
READONLY error. See crate::Store::open_replica for the
convenience constructor.
Sourcepub fn with_replica_id(self, id: impl Into<String>) -> Self
pub fn with_replica_id(self, id: impl Into<String>) -> Self
Override the replica identity sent to the primary at handshake. Useful when multiple embed replicas share one primary — otherwise they’d share the slot and stomp each other’s session state.
Sourcepub fn with_replica_reconnect(self, min: Duration, max: Duration) -> Self
pub fn with_replica_reconnect(self, min: Duration, max: Duration) -> Self
Override the replica reconnect backoff bounds.
Sourcepub fn with_embed_writer(self, bind_addr: impl Into<String>) -> Self
pub fn with_embed_writer(self, bind_addr: impl Into<String>) -> Self
Run this store as an embed-as-writer: bind a replication
source listener on bind_addr so replicas can subscribe to
the writes applied here.
Sourcepub fn with_feed(self, buffer_size: u64) -> Self
pub fn with_feed(self, buffer_size: u64) -> Self
Enable the CDC feed (changes_since / changes_tail).
buffer_size = 0 keeps the 64 MB default; values cap at 1 GB.
Sourcepub fn with_embed_writer_backlog(self, bytes: usize) -> Self
pub fn with_embed_writer_backlog(self, bytes: usize) -> Self
Override the embed-as-writer backlog byte budget.
Sourcepub fn with_reaper_interval(self, iv: Duration) -> Self
pub fn with_reaper_interval(self, iv: Duration) -> Self
Override the background reaper interval. Default 100 ms.
Source§impl Config
impl Config
Sourcepub fn with_tier_budget(self, bytes: u64) -> Self
pub fn with_tier_budget(self, bytes: u64) -> Self
Enable transparent tiering with a RAM budget of bytes: values
past the demote watermark spill to the cold tier on disk
(<data_dir>/tier/) and page back in on access — every command
keeps its exact semantics. Requires Self::with_persist; a
memory-only store fails at open with a named error.
Sourcepub fn with_tier_budget_auto(self) -> Self
pub fn with_tier_budget_auto(self) -> Self
Enable transparent tiering with the auto budget: 0.70 × the
detected memory bound (cgroup v2 limit / MemAvailable on
Linux, hw.memsize on macOS), re-probed on every reaper tick.
Open fails with a named error when no bound is detectable.
Sourcepub fn with_max_spill_value(self, bytes: u64) -> Self
pub fn with_max_spill_value(self, bytes: u64) -> Self
Cap the largest spillable value (bytes; 0 = unlimited). Bounds the embedded cold-read lock-hold time; default 256 KiB.
Sourcepub fn with_tier_budget_percent(self, p: u8) -> Self
pub fn with_tier_budget_percent(self, p: u8) -> Self
Enable transparent tiering with a percent-of-detected-bound
budget (p in 1..=100 — validated at open with a named error,
like every other config refusal).
Source§impl Config
impl Config
Sourcepub fn with_replica_security(self, keys: LinkKeys) -> Self
pub fn with_replica_security(self, keys: LinkKeys) -> Self
Encrypt the link to the replication upstream: the replica presents
keys.local and connects only to a primary holding one of
keys.peers. Opening fails when keys.peers is empty.
use kevy_embedded::{Config, Keypair, LinkKeys, Store};
let primary = Keypair::from_secret([2; 32]);
let replica = |peers| {
Config::default()
.without_aof()
.with_replica_upstream("127.0.0.1:16004")
.with_replica_security(LinkKeys::new(Keypair::from_secret([1; 32])).with_peers(peers))
};
assert!(Store::open(replica(vec![primary.public()]))?.is_replica());
// a secure replica that trusts no primary does not open
assert!(Store::open(replica(vec![])).is_err());Sourcepub fn with_writer_security(self, keys: LinkKeys) -> Self
pub fn with_writer_security(self, keys: LinkKeys) -> Self
Encrypt the embed-writer listener: every replica must complete a
Noise handshake against keys.local, and when keys.peers is not
empty, present one of those keys.
use kevy_embedded::{Config, Keypair, LinkKeys, Store};
let writer = Store::open(
Config::default()
.with_embed_writer("127.0.0.1:0")
.with_writer_security(LinkKeys::new(Keypair::from_secret([1; 32]))),
)?;
assert!(writer.writer_addr().is_some());Source§impl Config
impl Config
Sourcepub fn with_replay_mode(self, mode: ReplayMode) -> Self
pub fn with_replay_mode(self, mode: ReplayMode) -> Self
Best-effort replay: recover the good records BEHIND a corrupt v2
record instead of dropping them (a production incident lost a
231 MB well-formed tail over one bad frame). The skip is
deterministic — length + CRC32C + an exactly-one-command parse must
all agree before a record is trusted — and the open still reports
corrupt so hosts still alert. ReplayMode::Strict (the
default) remains the conservative choice: nothing after the first
bad byte is trusted.
use kevy_embedded::{Config, ReplayMode};
let cfg = Config::default().with_replay_mode(ReplayMode::Resync);
assert_eq!(cfg.replay_mode, ReplayMode::Resync);Sourcepub fn with_stage_ring(self, bytes: u64) -> Self
pub fn with_stage_ring(self, bytes: u64) -> Self
Stage appends in a ring of bytes per shard (a power of two, at
least 64 KiB), or turn staging off with 0. See
Config::stage_bytes.
let config = kevy_embedded::Config::default().with_stage_ring(1 << 20);
assert_eq!(config.stage_bytes, 1 << 20);Sourcepub fn with_mapped_aof(self, on: bool) -> Self
pub fn with_mapped_aof(self, on: bool) -> Self
Append through a mapping of the AOF (true) or through write().
See Config::mapped_aof.
let config = kevy_embedded::Config::default().with_mapped_aof(false);
assert!(!config.mapped_aof);