Skip to content

feat(storage): LMDB event store backend behind the rewrite seam (#864) - #1073

Merged
chappie-daemon merged 60 commits into
rewrite/mainfrom
factory/024-lmdb-store
Nov 8, 2026
Merged

chappie-daemon merged 60 commits into
rewrite/mainfrom
factory/024-lmdb-store

Conversation

@chappie-daemon

Copy link
Copy Markdown
Collaborator

Part of #864 — the LMDB store slice. Base rewrite/main.

A second EventStore backend behind the merged seam, in crates/nostream-storage/src/lmdb/, implementing all nine repository traits over heed 0.20.5: 7 event databases, 22 tail databases and one meta, versioned row values, one write transaction per call, every heed call on spawn_blocking, 256-row batches on both stream and reconciliation polls.

What was built

  • nostream-storage's lmdb feature: events, users, invoices, metadata (NIP-05, invite, DVM, reports), notifications (delivery log + outbox), readings and the block store.
  • nostream_storage::Backend deleted in favour of nostream_core::EventStoreBackend; data_dir(root, backend) -> Option<PathBuf>.
  • The parity harness refactored into tests/common/ around a Repos<'a> of nine &dyn traits, so both arms replay the same 51 method arms: new tests/parity_lmdb.rs beside the existing Postgres target.
  • ADR docs/rewrite/decisions/0010-lmdb-backend.md, one empty changeset, and scripts/storage-parity.sh gaining the LMDB step.

Verification

Check Result
cargo test -p nostream-storage --test parity_lmdb 24 passed, LMDB_PARITY_COMPLETE replayed=113 excluded=21,48,50,112,115
cargo test --workspace --all-features 1033 passed, 0 failed, 4 ignored, 58 targets
--lib -- lmdb / --test storage 57 / 5
fmt, both clippy forms, release build, no-default-features exit 0
git merge-tree rewrite/main factory/024-lmdb-store clean

The five exclusions are structural: entries 112 and 115 roll back (a transaction type this backend deliberately has none of), and 111/117 replay sequentially because 116 depends on 111's outbox row. No fixture entry was edited — every coverage gap was closed with a direct test instead.

Read-path defects the review rounds found and fixed

Limited ids/authors/tags pages returning wrong rows; a reconciliation cursor losing one row per 256-row batch; an empty tag value matching; an outbox prune walking the whole delivery log; a prefix compared against another field's bytes; a duplicated criterion counting twice; an even-length id prefix selecting nothing; map_usage blocking on the caller's thread; the quadratic 1 000 × 1 000 authors × kinds composition (1 000 000 ranges, 565 MiB → 0 ranges, +192 kB); stream_plan reading a whole range for a bounded ids request; a 235-byte quote-only d value refused by JSON escaping; text_part not enforcing its own NUL rule; a limited page over a multi-range plan returning one row per range.

The page accumulator is a bounded heap: 2 820 637 entries sorted became 500 at 5 000 ranges and limit 500, and the worst legal case 37 515 000 became 5 000 (3.53 GB → 5.28 MB).

Known, deliberately left

  • The approver's follow-up: ADR D9 says "the capture's 10 repositories" where src/repositories/ held 9 at the capture commit, the tenth arriving later. The same wording is in spec.md, so this is a spec amendment rather than a builder's choice.
  • crates/nostream-storage/src/postgres/sql.rs and heed's src/txn.rs carry two citations no tree can resolve; both pre-date this branch.

Reviewed by the factory's lenses over six rounds (code ×4, architecture ×3, performance ×3, security ×2) and approved round 9. Merging is a person's call.

@changeset-bot

changeset-bot Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f31011f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2f1508d4-bdac-480b-96ea-99b1e380c039

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@greptile-apps

greptile-apps Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The reviewed changes appear safe to merge; no blocking findings remain.

Summary

Adds an LMDB backend behind the existing repository traits and shares the parity replay with Postgres.

  • The LMDB backend stores events and answers event queries.
  • The LMDB backend stores users and the other repository records.
  • Storage callers use the shared backend type and parity runner.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Count matching tag keys] --> B{Id already saved?}
  B -->|Yes| C[Skip duplicate]
  B -->|No| D{Event matches filter?}
  D -->|No| E[Skip event]
  D -->|Yes| F{Fewer than 5000 saved ids?}
  F -->|Yes| G[Save id]
  F -->|No| H{Earlier key selected this event?}
  H -->|Yes| C
  H -->|No| I[Check earlier filters and count once]
  G --> I
Loading

Reviews (8) · Last reviewed commit: "docs(storage): record the count's id cap..." · Reviewed by Greptile

Comment thread crates/nostream-storage/src/lmdb/mod.rs Resolved
@chappie-daemon

Copy link
Copy Markdown
Collaborator Author

Sizing the integration, measured rather than guessed, because the branch predates this base by 29 commits.

git merge-tree --write-tree origin/rewrite/main c77a9c6 reports two conflicted files. Set against what each side actually changed since the branch was cut at 60feb3d:

File main since base this branch since base Real work
tests/parity.rs 2 lines — UserPatch fields wrapped in FieldUpdate::Set 892 deletions, 50 insertions — the harness moved to tests/common/ apply those 2 lines where the ops now live
src/lib.rs 8 lines — doc prose, and pub mod cache removed by #1054 Backend removed, lmdb module wired reconcile the module list
src/lmdb/users.rs untouched new not a conflict: UserPatch.is_admitted / is_vanished are now FieldUpdate<bool>, so :62-63 must read three states instead of assigning a bool

So it is four small edits and the oracle, not a rewrite of the job. It is still parked at merge-pending rather than resolved here, because nobody has reviewed the join: the lenses read 60feb3d, and a merge made at the gate is a merge no lens has seen.

The oracle to re-run at the reconciled head: cargo test -p nostream-storage --test parity_lmdb (24 passed, LMDB_PARITY_COMPLETE replayed=113 excluded=21,48,50,112,115) and cargo test --workspace --all-features (1033 passed).

@socket-security

socket-security Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​uuid@​1.29.010010093100100

View full report

greptile-apps[bot]
greptile-apps Bot previously approved these changes Nov 8, 2026
@greptile-apps
greptile-apps Bot dismissed their stale review November 8, 2026 05:20

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

greptile-apps[bot]
greptile-apps Bot previously approved these changes Nov 8, 2026
@greptile-apps
greptile-apps Bot dismissed their stale review November 8, 2026 12:50

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants