diff --git a/differences.md b/differences.md index d344ad8..852cd9b 100644 --- a/differences.md +++ b/differences.md @@ -417,33 +417,36 @@ The following items from the original gap list have been implemented: ## 11. JetStream -> The Go JetStream surface is ~37,500 lines across jetstream.go, stream.go, consumer.go, filestore.go, memstore.go, raft.go. The .NET implementation has ~700 lines covering a minimal subset. Verified by `JetStreamApiRouter.cs` registration. +> The Go JetStream surface is ~37,500 lines across jetstream.go, stream.go, consumer.go, filestore.go, memstore.go, raft.go. The .NET implementation has expanded API and runtime parity coverage but remains partial versus full Go semantics. ### JetStream API ($JS.API.* subjects) | Subject | Go | .NET | Notes | |---------|:--:|:----:|-------| -| `STREAM.CREATE.` | Y | Y | Only API handler implemented | +| `STREAM.CREATE.` | Y | Y | | | `STREAM.INFO.` | Y | Y | | -| `STREAM.UPDATE.` | Y | N | | -| `STREAM.DELETE.` | Y | N | | -| `STREAM.NAMES` | Y | N | | -| `STREAM.LIST` | Y | N | | -| `STREAM.PURGE.` | Y | N | Storage has `PurgeAsync()` but no API handler | -| `STREAM.MSG.GET.` | Y | N | | -| `STREAM.MSG.DELETE.` | Y | N | | -| `DIRECT.GET.` | Y | N | KV-style direct access | +| `STREAM.UPDATE.` | Y | Y | | +| `STREAM.DELETE.` | Y | Y | | +| `STREAM.NAMES` | Y | Y | | +| `STREAM.LIST` | Y | Y | | +| `STREAM.PURGE.` | Y | Y | | +| `STREAM.MSG.GET.` | Y | Y | | +| `STREAM.MSG.DELETE.` | Y | Y | | +| `DIRECT.GET.` | Y | Y | Includes direct payload response shape | | `CONSUMER.CREATE.` | Y | Y | | | `CONSUMER.INFO..` | Y | Y | | -| `CONSUMER.DELETE..` | Y | N | | -| `CONSUMER.NAMES.` | Y | N | | -| `CONSUMER.LIST.` | Y | N | | -| `CONSUMER.PAUSE..` | Y | N | | -| `STREAM.LEADER.STEPDOWN.` | Y | N | | -| `META.LEADER.STEPDOWN` | Y | N | | -| `STREAM.SNAPSHOT.` | Y | N | | -| `STREAM.RESTORE.` | Y | N | | -| `INFO` (account info) | Y | N | | +| `CONSUMER.DELETE..` | Y | Y | | +| `CONSUMER.NAMES.` | Y | Y | | +| `CONSUMER.LIST.` | Y | Y | | +| `CONSUMER.PAUSE..` | Y | Y | | +| `CONSUMER.RESET..` | Y | Y | | +| `CONSUMER.UNPIN..` | Y | Y | | +| `CONSUMER.MSG.NEXT..` | Y | Y | | +| `STREAM.LEADER.STEPDOWN.` | Y | Y | | +| `META.LEADER.STEPDOWN` | Y | Y | | +| `STREAM.SNAPSHOT.` | Y | Y | Snapshot/restore shape implemented; in-memory semantics | +| `STREAM.RESTORE.` | Y | Y | Snapshot/restore shape implemented; in-memory semantics | +| `INFO` (account info) | Y | Y | | ### Stream Configuration @@ -452,8 +455,8 @@ The following items from the original gap list have been implemented: | Subjects | Y | Y | | | Replicas | Y | Y | Wires RAFT replica count | | MaxMsgs limit | Y | Y | Enforced via `EnforceLimits()` | -| Retention (Limits/Interest/WorkQueue) | Y | N | Only MaxMsgs trimming; Interest and WorkQueue not implemented | -| Discard policy (Old/New) | Y | N | | +| Retention (Limits/Interest/WorkQueue) | Y | Partial | Policy enums + validation branch exist; full runtime semantics incomplete | +| Discard policy (Old/New) | Y | Partial | Model support exists; runtime discard behavior not fully enforced | | MaxBytes / MaxAge (TTL) | Y | N | | | MaxMsgsPer (per-subject limit) | Y | N | | | MaxMsgSize | Y | N | | @@ -474,16 +477,16 @@ The following items from the original gap list have been implemented: | Ephemeral consumers | Y | N | Only durable | | AckPolicy.None | Y | Y | | | AckPolicy.Explicit | Y | Y | `AckProcessor` tracks pending with expiry | -| AckPolicy.All | Y | N | | +| AckPolicy.All | Y | Partial | In-memory ack floor behavior implemented; full wire-level ack contract remains limited | | Redelivery on ack timeout | Y | Partial | `NextExpired()` detects expired; limit not enforced | -| DeliverPolicy (All/Last/New/StartSeq/StartTime) | Y | N | Always delivers from beginning | +| DeliverPolicy (All/Last/New/StartSeq/StartTime) | Y | Partial | Policy enums added; fetch behavior still mostly starts at beginning | | FilterSubject (single) | Y | Y | | | FilterSubjects (multiple) | Y | N | | | MaxAckPending | Y | N | | -| Idle heartbeat | Y | N | Field in model; not implemented | +| Idle heartbeat | Y | Partial | Push engine emits heartbeat frames for configured consumers | | Flow control | Y | N | | | Rate limiting | Y | N | | -| Replay policy | Y | N | | +| Replay policy | Y | Partial | Policy enum exists; replay timing semantics not fully implemented | | BackOff (exponential) | Y | N | | ### Storage Backends @@ -515,7 +518,7 @@ MemStore has basic append/load/purge with `Dictionary` unde | Feature | Go (5 037 lines) | .NET (212 lines) | Notes | |---------|:--:|:----:|-------| | Leader election / term tracking | Y | Partial | In-process; nodes hold direct `List` references | -| Log append + quorum | Y | Partial | Entries replicated via direct method calls; no network | +| Log append + quorum | Y | Partial | Entries replicated via direct method calls; stale-term append now rejected | | Log persistence | Y | N | In-memory `List` only | | Heartbeat / keep-alive | Y | N | | | Log mismatch resolution (NextIndex) | Y | N | | @@ -587,13 +590,12 @@ MemStore has basic append/load/purge with `Dictionary` unde 5. **Route pooling** — single connection per peer vs Go's 3-connection pool ### JetStream (Significant Gaps) -1. **API coverage** — Only 4 of ~20 `$JS.API.*` subjects handled (STREAM.CREATE/INFO, CONSUMER.CREATE/INFO) -2. **Stream delete/update/list** — not implemented -3. **Consumer delete/list/pause** — not implemented -4. **Retention policies** — only MaxMsgs; Interest and WorkQueue retention absent -5. **FileStore scalability** — JSONL-based (not block/compressed/encrypted) -6. **RAFT persistence** — in-memory only; cluster restart loses all JetStream state -7. **Consumer delivery completeness** — DeliverPolicy, AckPolicy.All, MaxAckPending, heartbeats, flow control absent +1. **API coverage is expanded but still incomplete** — core stream/consumer/direct/control routes are implemented, but full Go surface and edge semantics remain +2. **Policy/runtime semantics are incomplete** — retention/discard/delivery/replay models exist, but behavior does not yet match Go across all cases +3. **Snapshot/restore and cluster control are skeletal** — request/response contracts exist; durable/distributed semantics remain limited +4. **FileStore scalability** — JSONL-based (not block/compressed/encrypted) +5. **RAFT persistence and transport** — in-memory coordination; no durable log/RPC transport parity +6. **Consumer delivery completeness** — MaxAckPending, flow control, replay/backoff, and full fetch/ack lifecycle parity still incomplete ### Lower Priority 1. **Dynamic buffer sizing** — delegated to Pipe, less optimized for long-lived connections @@ -604,7 +606,7 @@ MemStore has basic append/load/purge with `Dictionary` unde --- -## 10. JetStream Remaining Parity (2026-02-23) +## 13. JetStream Remaining Parity (2026-02-23) ### Newly Ported API Families - `$JS.API.INFO`