feat: Jetstream consumer — JSON event streaming with server-side filtering (closes #43) #44

Closed
Grandiras wants to merge 2 commits from feat/jetstream-consumer into main
Owner
  • JetstreamClient: single WebSocket to /subscribe with wantedCollections
    (NSIDs + prefix wildcards, max 100), wantedDids (max 10k), cursor
    (unix microseconds), maxMessageSizeBytes; https->wss scheme conversion
  • JetstreamConsumer: managed consumer with reconnect backoff, cursor
    persistence via existing IFirehoseCursorStore (cursor = time_us),
    reconnect rewind with duplicate suppression, at-least-once semantics
  • JetstreamEventParser: forward-tolerant commit/identity/account parsing;
    unknown kinds/operations/fields skipped instead of throwing
  • JetstreamCommitEvent.GetRecord() honours LexiconTypeRegistry; computed at:// Uri
  • IJetstreamDecompressor seam for optional zstd (no bundled dependency;
    ZstdSharp sample in docs)
  • 49 unit tests (parser frames, URL building, consumer resume/rewind/dedup);
    live smoke-tested against jetstream2.us-east.bsky.network incl. cursor replay
  • docs/jetstream.md with firehose comparison + non-verifiability caveat

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

- JetstreamClient: single WebSocket to /subscribe with wantedCollections (NSIDs + prefix wildcards, max 100), wantedDids (max 10k), cursor (unix microseconds), maxMessageSizeBytes; https->wss scheme conversion - JetstreamConsumer: managed consumer with reconnect backoff, cursor persistence via existing IFirehoseCursorStore (cursor = time_us), reconnect rewind with duplicate suppression, at-least-once semantics - JetstreamEventParser: forward-tolerant commit/identity/account parsing; unknown kinds/operations/fields skipped instead of throwing - JetstreamCommitEvent.GetRecord<T>() honours LexiconTypeRegistry; computed at:// Uri - IJetstreamDecompressor seam for optional zstd (no bundled dependency; ZstdSharp sample in docs) - 49 unit tests (parser frames, URL building, consumer resume/rewind/dedup); live smoke-tested against jetstream2.us-east.bsky.network incl. cursor replay - docs/jetstream.md with firehose comparison + non-verifiability caveat Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat: Jetstream consumer — JSON event streaming with server-side filtering (closes #43)
Some checks failed
CI / build-and-test (pull_request) Has been cancelled
396e0d338b
- JetstreamClient: single WebSocket to /subscribe with wantedCollections
  (NSIDs + prefix wildcards, max 100), wantedDids (max 10k), cursor
  (unix microseconds), maxMessageSizeBytes; https->wss scheme conversion
- JetstreamConsumer: managed consumer with reconnect backoff, cursor
  persistence via existing IFirehoseCursorStore (cursor = time_us),
  reconnect rewind with duplicate suppression, at-least-once semantics
- JetstreamEventParser: forward-tolerant commit/identity/account parsing;
  unknown kinds/operations/fields skipped instead of throwing
- JetstreamCommitEvent.GetRecord<T>() honours LexiconTypeRegistry; computed at:// Uri
- IJetstreamDecompressor seam for optional zstd (no bundled dependency;
  ZstdSharp sample in docs)
- 49 unit tests (parser frames, URL building, consumer resume/rewind/dedup);
  live smoke-tested against jetstream2.us-east.bsky.network incl. cursor replay
- docs/jetstream.md with firehose comparison + non-verifiability caveat

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Grandiras force-pushed feat/jetstream-consumer from 396e0d338b
Some checks failed
CI / build-and-test (pull_request) Has been cancelled
to 626f64c28f
Some checks failed
CI / build-and-test (pull_request) Has been cancelled
2026-07-05 17:20:00 +00:00
Compare
Author
Owner

@claude-bot Please fix the conflict.

@claude-bot Please fix the conflict.
Collaborator

🤖 On it — follow along in the action run; the reply will link the full session transcript.

🤖 On it — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/33); the reply will link the full session transcript.
Merge branch 'main' into feat/jetstream-consumer
All checks were successful
CI / build-and-test (pull_request) Successful in 39s
Sync Closures to GitHub / sync-closure (pull_request) Successful in 7s
400554fd00
Resolves the CHANGELOG.md conflict: both branches appended entries under
[Unreleased] > Added (Jetstream #43 vs. OAuth handle-resolution #52); kept
both sets.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Collaborator

Conflict resolved and pushed — the PR should be mergeable again.

What the conflict was: only CHANGELOG.md. The branch was cut at c195f77, and main has since picked up four commits (#48, #51, #54, #53). Both sides appended bullets to the same ## [Unreleased]### Added block — the Jetstream entries (#43) here, the OAuth HandleResolutionTimeout / HttpClient / HttpClientTimeout entries (#52) on main. Not a semantic conflict, just adjacent additions.

Resolution: kept both sets of bullets in ### Added, Jetstream first, then the #52 entries. No other file conflicted — git merge auto-merged everything else cleanly, including the main-side changes to LexiconTypeRegistry and AtProtoJsonDefaults that the Jetstream code touches indirectly (JetstreamCommitEvent.GetRecord<T>() goes through LexiconTypeRegistry.CreateOptions(), which now sets AllowOutOfOrderMetadataProperties — the Jetstream path inherits that fix rather than fighting it).

Verified on the merged tree, in a freshly installed .NET 10.0.302 SDK:

  • dotnet build -p:EnableSourceControlManagerQueries=false0 errors (1160 warnings, all pre-existing CS1591 missing-XML-doc and the known RZ10012/NU1902 ones).
  • dotnet test tests/ATProtoNet.Tests/ -p:EnableSourceControlManagerQueries=false994 passed, 0 failed, 0 skipped. That covers both the 49 Jetstream tests from this branch and the new main-side OAuth/PLC/out-of-order-$type tests together.

Pushed as merge commit 400554f on branch feat/jetstream-consumer. I did not squash or rebase, so the original 626f64c review history is intact.


⏱ 1m 50s · 16 turns · tokens: 24.3k in / 3.5k out (+492.3k cache-read)
📜 Full session transcript

Conflict resolved and pushed — the PR should be mergeable again. **What the conflict was:** only `CHANGELOG.md`. The branch was cut at `c195f77`, and `main` has since picked up four commits (#48, #51, #54, #53). Both sides appended bullets to the same `## [Unreleased]` → `### Added` block — the Jetstream entries (#43) here, the OAuth `HandleResolutionTimeout` / `HttpClient` / `HttpClientTimeout` entries (#52) on `main`. Not a semantic conflict, just adjacent additions. **Resolution:** kept both sets of bullets in `### Added`, Jetstream first, then the #52 entries. No other file conflicted — `git merge` auto-merged everything else cleanly, including the `main`-side changes to `LexiconTypeRegistry` and `AtProtoJsonDefaults` that the Jetstream code touches indirectly (`JetstreamCommitEvent.GetRecord<T>()` goes through `LexiconTypeRegistry.CreateOptions()`, which now sets `AllowOutOfOrderMetadataProperties` — the Jetstream path inherits that fix rather than fighting it). **Verified** on the merged tree, in a freshly installed .NET 10.0.302 SDK: - `dotnet build -p:EnableSourceControlManagerQueries=false` — **0 errors** (1160 warnings, all pre-existing CS1591 missing-XML-doc and the known `RZ10012`/`NU1902` ones). - `dotnet test tests/ATProtoNet.Tests/ -p:EnableSourceControlManagerQueries=false` — **994 passed, 0 failed, 0 skipped**. That covers both the 49 Jetstream tests from this branch and the new `main`-side OAuth/PLC/out-of-order-`$type` tests together. Pushed as merge commit `400554f` on branch `feat/jetstream-consumer`. I did not squash or rebase, so the original `626f64c` review history is intact. --- ⏱ 1m 50s · 16 turns · tokens: 24.3k in / 3.5k out (+492.3k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/ATProto.NET/issue-44/run-33.md)
Grandiras closed this pull request 2026-07-25 02:09:42 +00:00
All checks were successful
CI / build-and-test (pull_request) Successful in 39s
Sync Closures to GitHub / sync-closure (pull_request) Successful in 7s

Pull request closed

Sign in to join this conversation.
No description provided.