Skip to content

Catch up a boundary change a server was not listening for - #95

Merged
davidmckayv merged 1 commit into
mainfrom
fix/policy-fanout-reconnect
Aug 21, 2026
Merged

Catch up a boundary change a server was not listening for#95
davidmckayv merged 1 commit into
mainfrom
fix/policy-fanout-reconnect

Conversation

@davidmckayv

Copy link
Copy Markdown
Contributor

Two improvements from @NathanTarbert's #94, plus the changelog catching up with the last day.

#94 arrived five minutes after #90 merged, so we were working the same item in parallel without
knowing. His was better than mine in two places and both are worth having.

The reconnect re-read

A NOTIFY reaches whoever is listening at the time. A replica that was restarting, or whose
connection had dropped, is not, so it missed the announcement and went on enforcing the rules it read
at boot until something restarted it. That is the bug #88 item 1 describes wearing a smaller hat, and
worse for being intermittent: the fleet disagrees with itself and nothing says so.

The handler is now passed as onlisten as well as onnotify, so the row is re-read whenever the
driver establishes or re-establishes the subscription — exactly the moments a notification could have
been missed. I did not think of this.

The announcement inside the write transaction

Mine announced after the write returned. A write that rolled back could still have announced, and
there was a window where the row had committed and the other servers had not been told. It is in the
transaction now, so delivery happens on commit. channels/routes.ts already did it this way and I
should have copied it more closely.

Proof

Two tests. The reconnect one changes the rule while the server has no subscription, then establishes
one, and fails without onlisten. The rollback one asserts a listening server does not move when a
write fails.

bun run test:ci: 1008 tests, 0 fail. Typecheck and format clean.

Changelog

The last day of merges had run ahead of it: #28, #37, #45, #46, #90, #30 and #92 were all in main
and none were written down. Added, along with the two upgrade notes that came with them — the Bot id
rules, and AUDIT_RETENTION_DAYS.

The README is untouched. It is a build doc.

Where it runs

  • New state that outlives a request? None.
  • What happens on the second replica? It is the point: a replica that missed an announcement now
    catches up when its subscription returns, rather than at its next restart.
  • Anything serialised? The same single row, now written and announced in one transaction.
  • Anything fanned out to a browser? No.
  • New listener, port, or schedule? None beyond the one Put shared state where every replica can see it, and bound what grows #90 added.

Two improvements from Nathan Tarbert's #94, which arrived five minutes after #90 merged and was
better than it in these two places.

A NOTIFY reaches whoever is listening at the time. A replica that was restarting, or whose connection
had dropped, is not, so it missed the announcement and went on enforcing the rules it read at boot
until something restarted it. That is the original bug wearing a smaller hat and worse for being
intermittent: the fleet disagrees with itself and nothing says so. The handler is now passed as
`onlisten` as well, so the row is re-read whenever the driver establishes or re-establishes the
subscription, which is exactly when a notification could have been missed.

The announcement now goes inside the write transaction, so it is delivered on commit. A write that
rolls back announces nothing, and there is no window where the row has changed and the other servers
have not been told. Same shape as channel activity, which is what should have been copied.

Two tests. The reconnect one fails without `onlisten`.

The changelog also picks up the last day of merges, which had run ahead of it.
@davidmckayv
davidmckayv merged commit 2b2bc39 into main Aug 21, 2026
6 checks passed
@davidmckayv
davidmckayv deleted the fix/policy-fanout-reconnect branch August 21, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant