examples: MongoDB SessionStore reference adapter#1014
Open
alexbevi wants to merge 8 commits into
Open
Conversation
Adds a fourth reference SessionStore adapter under examples/session_stores/mongodb_session_store.py, alongside the existing S3, Redis, and Postgres adapters. Mirrors the Postgres adapter shape: one document per JSONL entry with server-assigned ObjectId ordering, plus a separate summaries collection maintained inside append() via fold_session_summary. Uses pymongo's stable async API (AsyncMongoClient, introduced in pymongo 4.13). Implements all five SessionStore methods plus list_session_summaries; serializes the read-fold-write summary update with a per-session asyncio Lock to satisfy the protocol's concurrency requirement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Required by examples/session_stores/mongodb_session_store.py. Pinned to >=4.13 (the first stable release of pymongo's async API, AsyncMongoClient). The corresponding test module importorskips on pymongo so default CI is unaffected when [examples] isn't installed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds tests/test_example_mongodb_session_store.py mirroring the Postgres test module: live-only via SESSION_STORE_MONGODB_URL, full 14-contract conformance harness, constructor validation, and an end-to-end TranscriptMirrorBatcher → MongoDB → materialize_resume_session round-trip. Each run uses a random database name and drops it on teardown. Verified locally against `docker run -d -p 27017:27017 mongo:latest`: 4 passed (conformance + duck-type probe + name validation + round-trip). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a MongoDB section to examples/session_stores/README.md mirroring the S3/Redis/Postgres sections (Installation, Usage, Schema, Concurrency, Retention, Resume, Live e2e, TS cross-reference) plus a MongoDB entry under the umbrella production checklist (pool sizing, multi-writer note, retention). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Calls out the divergence from the S3/Redis/Postgres adapters: this one implements the optional list_session_summaries method, which lets list_sessions_from_store() take its fast path (one batch read + gap-fill) instead of N per-session load() calls. Also flags the fold_session_summary import as a deliberate public-for-adapters use of the SDK's _internal package, with a localized comment so a future relocation is a single-line fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a TestAdapterSpecific class with four tests for behaviors the shared conformance harness cannot probe: - create_schema is idempotent (matches the Postgres adapter's extra test). - The dataclass options= constructor path is equivalent to positional args. - A targeted subpath delete leaves the main session's summary sidecar intact; only main delete cascades. - Concurrent appends carrying disjoint summary fields (customTitle vs gitBranch) must both survive — the per-session asyncio.Lock keeps the read-fold-write atomic across appends. Adversarially verified: removing the lock causes 29/30 trials to clobber one field. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Anticipates the contributing guide proposed in PR anthropics#1005 by: - Running ruff format on the adapter module and test file (previously passed `ruff check` but not `ruff format --check`). - Fixing two ruff B023 findings in the concurrency test, where inner closures captured the loop's `key` variable. Bound via default arg so each iteration gets its own value — same fix the linter recommends, prevents a real future bug if the loop body grows. After this change the package now passes the full set of checks the guide enumerates: `ruff check src/ tests/`, `ruff format --check src/ tests/`, and `mypy src/`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
Author
|
Note this is a follow up to anthropics/claude-agent-sdk-typescript#341 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A self-contained reference
SessionStoreimplementation for MongoDB underexamples/session_stores/mongodb_session_store.py, alongside the existing S3, Redis, and Postgres adapters. Imports types from the publishedclaude_agent_sdkpackage and passes the full 14-contract conformance suite atsrc/claude_agent_sdk/testing/session_store_conformance.py.mongodb_session_store.pypymongo(>=4.13)SESSION_STORE_MONGODB_URLStorage model
Two collections share one database. Entries — one document per JSONL transcript entry, ordered by the server-assigned
_id(ObjectId):{ "_id": ObjectId, "project_key": str, "session_id": str, "subpath": str, # "" sentinel for the main transcript "entry": <opaque JSON>, "mtime": int } # epoch msSummaries — one document per main session, maintained incrementally inside
append()viafold_session_summary:{ "_id": {"project_key": str, "session_id": str}, "mtime": int, "data": <opaque SDK-owned dict> }create_schema()creates three indexes (idempotent).append()is a singleinsert_manyplus an atomic summary upsert;load()isfind().sort("_id", 1).What's different from the other adapters
This adapter implements the optional
list_session_summariesmethod (S3/Redis/Postgres skip it via Protocol-default detection). That giveslist_sessions_from_store()its fast path — one batch read for all summaries plus a cheaplist_sessions()to gap-fill — instead of the fallback's N per-sessionload()calls (bounded at 16 concurrent). For projects with many sessions or remote-backend latency, the README explains the tradeoff.The summary read-fold-write inside
append()is serialized with a per-sessionasyncio.Lockto satisfy the protocol's concurrency requirement.Driver
Uses pymongo's stable async API (
pymongo.AsyncMongoClient, introduced in pymongo 4.13).pymongo>=4.13is added to the[examples]optional-dependency group; the test moduleimportorskipsso default CI is unaffected.Conformance with proposed CONTRIBUTING.md (#1005)
This PR was sanity-checked against the developer workflow proposed in #1005 — the package passes every check that guide will enforce on
src/andtests/:ruff check src/ tests/— clean (incl. ruff B023, which had flagged a closure-over-loop-variable bug in the concurrency test).ruff format --check src/ tests/— clean (the test file isruff format-stable).mypy src/— clean (no SDK source touched).feat:,chore:,test:,docs:).The adapter module under
examples/is outside the guide's required surface but is formatted to the same standard since it's reference code users copy-paste.Running
CI / packaging impact: none
Nothing under
examples/is packaged or built by repo CI. The test moduleimportorskipsonpymongoand module-level skips on the env var, so default CI is unaffected if[examples]isn't installed. No workflow files added; no CHANGELOG entry (examples are reference code, not versioned, perRELEASING.md).Verified locally against mongo:latest (mongod 8.2.5)
_store_implementsduck-type probe — pass.create_schema()idempotence — pass.options=constructor path equivalence — pass.delete()does NOT drop the summary sidecar — pass.TranscriptMirrorBatcher → MongoDB → materialize_resume_sessionround-trip — pass.Total: 8 passed in 0.89s.
Test plan
cd examples/session_stores && cat mongodb_session_store.pyfor reviewpip install -e '.[dev,examples]'ruff check src/ tests/— cleanruff format --check src/ tests/— cleanmypy src/— cleanpytest tests/test_example_mongodb_session_store.py— skips cleanly without envdocker run -d -p 27017:27017 mongo:latestthenSESSION_STORE_MONGODB_URL=mongodb://localhost:27017 pytest tests/test_example_mongodb_session_store.py -v— 8 passpytest tests/test_example_redis_session_store.py tests/test_example_s3_session_store.py— no regressions in sibling adapters