Create a new package, jido_bedrock, that provides distributed durable persistence for Jido agents and Jido signals on Bedrock without requiring Postgres or a larger external DB.
The package will implement three adapter surfaces:
Jido.Storagefor checkpoints + thread journals used byJido.Persist.Jido.Agent.Storefor InstanceManager hibernate/thaw persistence.Jido.Signal.Journal.Persistencefor signal docs, causality edges, conversation indexes, checkpoints, and DLQ.
Default mode must be durability-strict and fail fast if Bedrock cluster configuration is below a durable profile.
- New package at
jido_bedrockwith production-oriented adapters. - Shared key/codec/chunking internals.
- Durability profile checks and telemetry.
- Unit, contract, and distributed integration tests.
- Operator-facing documentation and examples.
- Changes to Jido/Jido Signal public APIs.
- Bedrock storage engine redesign.
- GUI/admin tooling.
Jido.Storage.BedrockimplementingJido.Storage.Jido.Agent.Store.BedrockimplementingJido.Agent.Store.Jido.Signal.Journal.Adapters.BedrockimplementingJido.Signal.Journal.Persistence.JidoBedrock.Configfor common adapter options.JidoBedrock.Durabilityfor profile validation and diagnostics.JidoBedrock.Codecbehavior with defaultJidoBedrock.Codec.BERT.JidoBedrock.Envelopefor chunk manifests and checksum validation.JidoBedrock.Keysfor canonical tuple-key construction.
All adapters accept:
:repo(required): module usingBedrock.Repo.:namespace(required): binary namespace isolation key.:codec(defaultJidoBedrock.Codec.BERT).:compress(defaulttrue).:chunk_size_bytes(default120_000).:durability_mode(default:strict, alt:relaxed).:retry_limit(default20).
Use tuple-packed keys rooted at:
{"jb", namespace, ...}
- Checkpoint manifest:
{"jb", ns, "jido", "ckpt", key_hash}
- Checkpoint chunks:
{"jb", ns, "jido", "ckpt_chunk", key_hash, idx}
- Thread meta:
{"jb", ns, "jido", "thread", thread_id, "meta"}
- Thread entry:
{"jb", ns, "jido", "thread", thread_id, "entry", seq}
- Agent dump manifest:
{"jb", ns, "agent_store", "dump", key_hash}
- Agent dump chunks:
{"jb", ns, "agent_store", "dump_chunk", key_hash, idx}
- Signal doc:
{"jb", ns, "signal", "doc", signal_id}
- Cause edge:
{"jb", ns, "signal", "cause_edge", cause_id, effect_id}
- Effect edge:
{"jb", ns, "signal", "effect_edge", effect_id, cause_id}
- Conversation edge:
{"jb", ns, "signal", "conv_edge", conversation_id, signal_id}
- Subscription checkpoint:
{"jb", ns, "signal", "checkpoint", subscription_id}
- DLQ by-subscription:
{"jb", ns, "signal", "dlq_sub", subscription_id, inserted_at_us, entry_id}
- DLQ pointer by-id:
{"jb", ns, "signal", "dlq_id", entry_id}
key_hash = Base.url_encode64(:crypto.hash(:sha256, :erlang.term_to_binary(key)), padding: false)
- Inline encode when serialized payload is
<= 128 KiB. - Chunk when payload exceeds limit.
- Manifest fields:
versioncodeccompressedchunk_countchecksumoriginal_size
- Read path validates checksum and chunk continuity.
- Corruption returns explicit adapter error, not silent fallback.
get_checkpoint/2
- Resolve checkpoint manifest + chunks.
- Return
:not_foundif absent.
put_checkpoint/3
- One Bedrock transaction writing manifest and chunks.
- Overwrite semantics.
delete_checkpoint/2
- Atomic delete of manifest + chunk range.
load_thread/2
- Read meta and range-scan entry keys.
- Rebuild
%Jido.Thread{}with consistentrev.
append_thread/3
- Read current
rev. - Enforce
:expected_rev; on mismatch callrollback(:conflict). - Write new sequential entries and update meta in one transaction.
delete_thread/2
- Clear thread entry range and meta atomically.
get/2: load envelope/chunks by hashed store key.put/3: atomic upsert manifest/chunks.delete/2: atomic delete manifest/chunks.
put_signal/2: upsert signal doc.get_signal/2: lookup by id with{:error, :not_found}semantics.put_cause/3: write cause/effect edge pair atomically.get_effects/2: range-scan cause edges intoMapSet.get_cause/2: range-scan effect edges and return deterministic first cause id.put_conversation/3: upsert conversation edge.get_conversation/2: range-scan conversation edges intoMapSet.put_checkpoint/3: upsert subscription checkpoint.get_checkpoint/2: lookup checkpoint with{:error, :not_found}.delete_checkpoint/2: delete checkpoint key.put_dlq_entry/5: writedlq_subanddlq_idpointer atomically.get_dlq_entries/2: range-scandlq_subkeys, naturally sorted by key.delete_dlq_entry/2: resolve pointer, delete both records atomically.clear_dlq/2: scan subscription DLQ keys and delete in bounded batches.
Adapter init must validate runtime cluster profile before serving writes.
Required minimums:
desired_replication_factor >= 3desired_logs >= 3- Persistent paths configured for coordinator, log, and storage roles.
Failure behavior:
- Return
{:error, {:durability_profile_failed, reason}}. - Emit telemetry failure event.
- Allows startup with warnings and telemetry annotations.
- Keeps semantics identical but does not claim strict profile compliance.
Emit:
[:jido_bedrock, :durability, :profile, :ok][:jido_bedrock, :durability, :profile, :failed][:jido_bedrock, :adapter, :operation, :stop][:jido_bedrock, :adapter, :operation, :exception]
Metadata includes adapter module, operation name, namespace, duration, and error class.
- Bootstrap package skeleton, dependencies, CI matrix.
- Build shared internals (
Config,Keys,Codec,Envelope, tx helpers). - Implement
Jido.Storage.Bedrock+ contract tests. - Implement
Jido.Agent.Store.Bedrock+ tests. - Implement
Jido.Signal.Journal.Adapters.Bedrock+ tests. - Implement durability checks and strict/relaxed modes.
- Build distributed integration harness (3-node Bedrock cluster).
- Finish docs/examples/release notes.
- Match behavior from existing ETS/File/Mnesia adapters for all callbacks.
- Validate
expected_revconflict behavior and thread ordering. - Validate DLQ ordering/filtering and checkpoint semantics.
- Chunk boundary and reassembly correctness.
- Checksum mismatch and corruption handling.
- Safe decode behavior for persisted terms.
- Concurrent
append_thread/3calls with same expected rev. - Concurrent signal causality updates.
- 3-node happy path writes and reads.
- Node restart survival for checkpoints, thread entries, and signals.
- Leader failover during active workload.
- Strict profile pass/fail verification.
0.1.0-alpha: core adapters + local tests.0.2.0-beta: strict profile checks + distributed tests.1.0.0-rc: full docs and migration guidance.1.0.0: production gate after durability acceptance criteria validation.
- Package root will be
/Users/mhostetler/Source/Jido/jido_bedrock. - Namespace is mandatory and per-environment.
- Default codec is BERT with safe decode.
- Compression defaults to enabled.
- Chunk size defaults to
120_000bytes. - Durability mode defaults to
:strict. get_cause/2returns deterministic lexicographically first cause id.
- All adapter callbacks implemented and tested.
Jido.Persisthibernate/thaw works end-to-end using Bedrock adapter.Jido.Signal.Journaloperations work end-to-end using Bedrock adapter.- Strict durability mode fails fast on under-provisioned cluster profiles.
- Distributed restart/failover integration tests pass in CI.