Swamp repo that measures and garbage-collects the shared @keeb/mongodb-datastore
  • TypeScript 79.1%
  • Python 20.9%
Find a file
keeb 82a5701bb4 Publish as @keeb/mongodb-stats 2026.09.02.1
Add manifest.yaml, MIT LICENSE.txt, and JSDoc on both extension exports.
Replace the /home/keeb HOME fallback in datastore_gc with an explicit error,
drop the datastore host from the README, and document the janitor repo's
hardcoded connection assumptions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 09:23:05 -07:00
.claude/skills swamp repo upgrade 2026-09-02 09:19:00 -07:00
bench Initial commit: mongo-stats swamp repo 2026-09-02 09:17:09 -07:00
extensions/models Publish as @keeb/mongodb-stats 2026.09.02.1 2026-09-02 09:23:05 -07:00
models/@keeb/mongodb Initial commit: mongo-stats swamp repo 2026-09-02 09:17:09 -07:00
vaults/local_encryption Initial commit: mongo-stats swamp repo 2026-09-02 09:17:09 -07:00
workflows Initial commit: mongo-stats swamp repo 2026-09-02 09:17:09 -07:00
.gitignore swamp repo upgrade 2026-09-02 09:19:00 -07:00
.swamp.yaml swamp repo upgrade 2026-09-02 09:19:00 -07:00
CLAUDE.md swamp repo upgrade 2026-09-02 09:19:00 -07:00
LICENSE.txt Publish as @keeb/mongodb-stats 2026.09.02.1 2026-09-02 09:23:05 -07:00
manifest.yaml Publish as @keeb/mongodb-stats 2026.09.02.1 2026-09-02 09:23:05 -07:00
README.md Publish as @keeb/mongodb-stats 2026.09.02.1 2026-09-02 09:23:05 -07:00

mongo-stats

A swamp repo that measures and garbage-collects a shared @keeb/mongodb-datastore. It is also published as the @keeb/mongodb-stats extension — swamp extension pull @keeb/mongodb-stats adds both methods to any @keeb/mongodb model.

It stores nothing of its own. It exists to report on the other repos that share that datastore — every swamp repo whose data lives in the swamp database as a t_<tenantId>_r_<namespace>_* collection triple.

Layout

Path What
models/@keeb/mongodb/ The one instance, treehouse — db swamp, URI from vault.get("mongo", "uri")
extensions/models/mongodb_datastore_stats.ts datastore_stats method
extensions/models/mongodb_datastore_gc.ts datastore_gc method
workflows/ The datastore-gc workflow (baseline → gc → verify)
bench/ Datastore-unit and end-to-end benchmarks against the real source

Both extensions layer onto the published @keeb/mongodb model, so the base query/find/insert methods are available on treehouse too.

How the datastore is laid out

One namespace = three collections, prefixed t_<tenantId>_r_<namespace>_:

  • _paths{ _id: relPath, hash, size, updatedAt, deletedAt }
  • _blobs{ _id: sha256, size, ...bytes }, content-addressed, so duplicates collapse server-side
  • _locks — distributed lock docs

relPath is rooted at a datastore subdir (data, outputs, workflow-runs, bundles, audit, telemetry, logs, …), which is what the per-subdir byte breakdown keys off.

Usage

How big is it?

swamp model method run treehouse datastore_stats
swamp data query 'modelName == "treehouse" && name == "queryResults"' \
  --select 'attributes.totals'

Aggregates every namespace server-side: active/deleted file counts, logical bytes by subdir, blob store size + count, and lock totals. Add attributes.repos for the per-namespace breakdown, or scope the run with --input namespace=<ns> / --input tenantId=<id>.

What would a GC reclaim?

swamp workflow run datastore-gc --input dryRun=true

Pulls a janitor mirror per namespace and runs swamp data gc --dry-run. Mutates nothing. Report gc.versionsDeleted and gc.bytesReclaimed.

Actually GC

swamp workflow run datastore-gc
swamp data query 'modelName == "treehouse" && name == "gcResults"' \
  --select 'attributes.totals'

Baseline stats → gc every namespace → verify stats, so the before/after delta lands as durable data.

Every method overwrites the instance's queryResults resource: stats land under key queryResults, gc under gcResults.

Things that will bite you

Blob bytes never shrink. The datastore has no blob GC. _blobs is append-only forever; gc only soft-tombstones _paths by setting deletedAt. Roughly 99.5% of the ~388 GB blob store is already orphaned and nothing here reclaims it. When someone asks how much a GC frees, say this out loud.

Sync counters lie about tombstones. filesPushed cheerfully reports 0 while tombstoning 160k paths. Trust the _paths re-count in gcResults (tombstoned / errors), never the CLI counter.

GC needs a complete mirror. The push sweep tombstones every remote path absent from the local mirror, so a partial or lazily-hydrated cache would tombstone everything unhydrated. That is why datastore_gc keeps its own cold pull under ~/.swamp/gc-janitor/<tenant>__<ns>/ (deterministic repoId, so the mirror survives between runs) instead of borrowing a writer repo's cache.

The janitor repo's connection settings are assumed, not derived. datastore_gc reuses only the host and credentials from mongodbUri; the janitor .swamp.yaml it writes hardcodes replicaSet=rs0, authSource=admin, directConnection=true, and passwordEnv: MONGO_PASSWORD. A cluster that differs on any of those needs the janitor config in mongodb_datastore_gc.ts adjusted. datastore_stats has no such assumption — it connects with the URI as given.

Benchmarks

bench/ measures the datastore's real sync paths, not mocks:

  • hydration_bench.ts — cold pullChanged(), full vs. metadataOnly lazy hydration, against a real namespace. Read-only.
  • pushchanged_bench.tspushChanged() timed directly against the real sync service (no swamp-core lock, no model execution), on scratch namespaces that are dropped afterward.
  • writeback_bench.py — the end-to-end analogue, driven through the actual swamp CLI and read out of swamp's own ms-resolution logs. Includes core's global lock and model execution, so it is not directly comparable to the datastore-unit numbers.

Reference

  • Base model: the mongodb skill (.claude/skills/mongodb/SKILL.md).
  • Datastore internals: ~/git/mongodb-swamp-datastore/extensions/datastores/mongodb/.
  • Method parameters: swamp model method describe treehouse — fetch them, don't memorize them.