feat(cache/jobs): fragment cache + tag-invalidation worker + block render cache + scheduled publisher - #489
Merged
Merged
Conversation
tayebmokni
enabled auto-merge (squash)
May 26, 2026 22:00
|
Heads up — this PR touches strings that often signal a security disclosure ( If this PR fixes or describes a real vulnerability that has not yet been publicly disclosed, please stop and use the private path:
See If this is a false positive (test fixture, doc update, release notes, etc.) please ignore this comment — the check is advisory only and does not block the PR. Matched commit messages:
|
Adds packages/go/cache/fragment with Get/Set/Purge over a Redis backend. Tag invalidation is decoupled from the cache itself: Purge appends rows into the cache_invalidations outbox shipped by 000030, and the invalidator worker fans the INCRs out to per-tag version counters via pub/sub. Reads validate the captured-vs-live version vector to detect stale entries. Layered as fragment (cache surface, no Postgres dep) + PgOutboxWriter (pgxpool insert) so unit tests don't need a database. Closes #91. Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
…tions Adds Subscriber to packages/go/cache/invalidator: PSUBSCRIBEs to the gonext:cache:invalidate channel published by the existing Worker, parses '<slug>:<tag>' payloads, and dispatches each invalidation to one or more registered HandlerFuncs. Handler errors are logged but do not stop the loop — the at-least-once delivery model assumes handlers are idempotent. Wires the Worker into apps/worker so the outbox actually drains in production, plus the shared pgx pool and dedicated Redis client the scheduler/GC jobs (#143) will reuse. Closes #94. Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
Adds CachedWalker — a Walker that consults a CacheBackend keyed by (version, block.type, sha256 of canonical encoding) before invoking each subtree's renderer. Production wires render.CacheBackend to cache/fragment.Cache; the fragment cache itself routes invalidation through the cache_invalidations outbox (#91/#94). Blocks that declare UsesContext or ProvidesContext bypass the cache because their output depends on ancestor state we cannot fold into the key. The remaining "leaf" blocks — paragraph, heading, image, list, etc. — dominate real-post content, which is what makes the 80%+ hit rate target on repeated renders achievable. Tests pin the hit rate at 83% after six identical-tree renders. The canonical encoder sorts attribute keys (Go's randomized map iteration would otherwise produce a different hash on each render of the same block). Closes #108. Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
Adds packages/go/jobs/scheduler with two cron-driven tasks:
* content.publisher.minute — fires every 1m, transitions posts
whose scheduled_for has elapsed from status='scheduled' to
status='published' via a single UPDATE … RETURNING. published_at
is preserved across re-publishes (COALESCE) so canonical
date-URLs stay stable.
* content.gc.daily — fires at 03:30 UTC, hard-deletes posts that
have been status='trash' for more than 30 days (configurable).
Trailing 30 minutes behind revisions.purge.daily so the two
heavy queries don't pile up at 03:00.
Both use the SELECT … FOR UPDATE SKIP LOCKED + CTE pattern so a
mis-fire from a non-leader replica is safely idempotent. Both have
LIMIT clauses (500 for publisher, 1000 for GC) to bound the lock
window — excess rows roll over to the next fire.
SeedDefaults wires both into the worker's taskspec + cron
registries; the worker's main.go calls it once the pgx pool is up.
Closes #143.
Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
tayebmokni
force-pushed
the
feat/cache-fragment-scheduler
branch
from
May 26, 2026 22:15
329edcd to
8bc7693
Compare
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.
Closes #91, #94, #108, #143.