Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .changeset/ipubsub-docblock-staleness-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
"@objectstack/core": patch
"@objectstack/service-cluster": patch
---

docs(core,service-cluster): retire the two docblocks left stale by `IPubSub`'s corrected delivery guarantee (#12836)

#12651 corrected `IPubSub`'s contract docblock: delivery is whatever the
configured driver declares, no shipped driver exceeds at-most-once, a missed
message is EXPECTED, and handlers must be idempotent **and** tolerate loss.
Two docblocks elsewhere still described the world before that correction.

**`@objectstack/core` — `security/authz-invalidation-channel.ts`.** It carried a
paragraph asserting, in the present tense, that the interface docblock "still
says" *At-least-once delivery*, and that repairing it was a `packages/spec`
change filed separately. That filing was #12651 and it has landed, so the
paragraph is now false rather than merely stale — it sends the next reader
looking for a live disagreement between the interface and the drivers that no
longer exists. Replaced with a plain pointer to the interface docblock.
Everything else in that docblock is unchanged: the at-most-once reasoning, the
TTL-is-the-bound rule, and the best-effort-at-the-publish-site note all still
hold.

**`@objectstack/service-cluster` — `memory/pubsub.ts`.** The line "At-least-once
semantics held vacuously (a single in-process delivery)" was wrong on its own
terms even before #12651: the same docblock states that handler errors are
swallowed and logged via `onError`, so a handler that throws loses the message
with no retry and no persistence. That is not at-least-once in any sense, and
"vacuously" does not save it. Replaced with the honest statement — one
synchronous in-process delivery attempt per subscriber, no persistence, no
retry, no replay.

Prose only. No behaviour change, and no test changed.
13 changes: 6 additions & 7 deletions packages/core/src/security/authz-invalidation-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@
* write that triggered it. A grant revocation must not fail because a cache
* hint could not be delivered — the TTL already covers exactly that case.
*
* ⚠️ Known contradiction in the surrounding docs, recorded so nobody resolves it
* the wrong way: `IPubSub`'s own interface docblock
* (`@objectstack/spec/contracts`) still says *"At-least-once delivery"*, which
* no shipped driver provides. `cluster.mdx` §4.2 and the redis driver are the
* measured statements and are the ones this module follows. Repairing that
* docblock is a `packages/spec` change and is filed separately, deliberately
* not made here.
* `IPubSub`'s own interface docblock (`@objectstack/spec/contracts`) states the
* same thing from the contract side — delivery is whatever the configured
* driver declares, no shipped driver exceeds at-most-once, and handlers must be
* idempotent **and** tolerate loss. That docblock, `cluster.mdx` §4.2 and the
* redis driver agree; there is no disagreement here for a later reader to go
* looking for.
*
* ## Why a new channel on the existing bus, and not a new transport
*
Expand Down
8 changes: 7 additions & 1 deletion packages/services/service-cluster/src/memory/pubsub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ import type {
* - Synchronous fan-out: every subscriber's handler is invoked in the
* same tick that `publish()` resolves. Handler errors are swallowed
* and logged via `onError` (so one bad subscriber can't poison the bus).
* - At-least-once semantics held vacuously (a single in-process delivery).
* - Delivery is at-most-once: one synchronous in-process attempt per
* subscriber, with no persistence, no retry and no replay. A handler that
* throws loses that message outright — the error is swallowed above and
* nothing redelivers it — and a publish to a channel nobody is subscribed
* to at that moment is a silent no-op. This matches what `IPubSub`
* documents: no shipped driver exceeds at-most-once, so handlers must be
* idempotent **and** tolerate loss.
* - No cross-process delivery — use the redis/postgres/nats driver for
* real multi-node setups.
*/
Expand Down
Loading