fix(digest): keep a subscriber's opt-out and run the Clerk sweep once a day - #721
Merged
Merged
Conversation
… a day The weekly digest is opt-out, so `reconcileSubscriptions` recreates a row for every current org member. It set `enabled = true` on conflict, which undid the two ways a subscriber can turn the digest off: `upsertSubscription` with `enabled: false`, and `deleteSubscription`, whose row the very next sweep recreated enabled. `enabled` now comes from a stored `opted_out_at`, so the sweep still re-enables a member it disabled itself when they left the org, but leaves a subscriber's own choice alone. `deleteSubscription` records that choice instead of erasing the only trace of it. The sweep's own 24-hour limiter never held either: it lived in a `Ref` owned by the service layer, and the alerting worker builds a fresh layer per cron invocation, so `lastSyncAt` started null on every tick. The digest cron fires every 15 minutes, so the sweep enumerated every Clerk org and member 96 times a day. It is now pinned to the first tick of the UTC day, which needs no state that survives an isolate.
Makisuo
force-pushed
the
fix/01-digest-opt-out-and-sweep-cadence
branch
from
September 1, 2026 14:51
4994fb8 to
766a848
Compare
🍁 Maple PR previewWarning Preview cleanup could not be confirmed. The Alchemy teardown outcome was Final commit |
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.
First of a five-PR stack. Each PR is based on the one below it — review and merge in order. Every commit typechecks standalone.
The weekly digest is opt-out, so
reconcileSubscriptionsrecreates a row for every current org member. It setenabled = trueon conflict, which undid both ways a subscriber can turn the digest off:upsertSubscriptionwithenabled: falsedeleteSubscription, whose row the very next sweep recreated enabledenabledis now recomputed from a storedopted_out_at(migration0053), so the sweep still re-enables a member it disabled itself when they left the org, but leaves a subscriber's own choice alone.deleteSubscriptionrecords that choice rather than erasing the only trace of it — a hard delete cannot survive an opt-out product.The sweep's own 24-hour limiter never held either. It lived in a
Refowned by the service layer, and the alerting worker builds a fresh layer per cron invocation, solastSyncAtstartednullon every tick. With the digest on the*/15cron that meant enumerating every Clerk org and member 96 times a day. It is pinned to the first tick of the UTC day now, which needs no state that survives an isolate.Note for the deploy
Production migrations are applied manually —
0053_digest_opt_out.sqladds one nullable column.Tests
Two regression tests in
DigestService.test.ts, both verified to fail against the old behaviour.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.