fix(gtc): clear projected data when a source table is truncated - #564
fix(gtc): clear projected data when a source table is truncated#564emoss08 wants to merge 1 commit into
Conversation
The WAL decoder already emitted TRUNCATE records, but no sink handled them: Meilisearch could not derive a document key from the data-less record (every truncate dead-lettered after retries) and the Redis JSON sink fell through to JSON.SET with a broken key, so truncated tables left all projected documents and cache keys stale. Meilisearch now deletes the projection's documents by filter on the _projection/_source_table metadata every document already carries, with those fields always registered as filterable so the delete works on shared indexes too. The Redis JSON sink renders the key template into a glob-escaped MATCH pattern (placeholders become wildcards) and removes matching keys via SCAN+UNLINK in batches, refusing patterns with no literal anchor so a truncate can never wipe the whole keyspace. Stream sinks already forward TRUNCATE events to consumers and are unchanged. Adds miniredis as a test dependency to cover the destructive delete path end to end. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015houJkqb8SuqPW4YpLoWCq
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (7)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe PR adds projection-scoped truncate handling to Meilisearch and Redis sinks. Redis truncation generates escaped wildcard patterns, scans matching keys, and deletes them in batches. Meilisearch truncation filters documents by projection metadata. ChangesProjection truncation
Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: 🟠 High · up to This PR changes Redis TRUNCATE handling to delete keys by wildcard pattern. Overlapping projection templates could remove another projection's keys, while interrupted or concurrent cleanup could leave inconsistent data, so the change is not merge-ready without stronger namespace isolation and cleanup convergence guarantees. Sequence Diagram(s)sequenceDiagram
participant SourceRecord
participant RedisSink
participant Template
participant Redis
SourceRecord->>RedisSink: OperationTruncate
RedisSink->>Template: WildcardPattern(record, primaryKeys)
Template-->>RedisSink: Projection-scoped key pattern
RedisSink->>Redis: Scan matching keys
RedisSink->>Redis: UNLINK keys in batches
sequenceDiagram
participant SourceRecord
participant MeilisearchSink
participant Meilisearch
SourceRecord->>MeilisearchSink: OperationTruncate
MeilisearchSink->>Meilisearch: Delete documents by projection and source-table filter
Meilisearch-->>MeilisearchSink: Task identifier
MeilisearchSink->>Meilisearch: Wait for truncate task
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 26 functions across 6 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
trenova | 4add5da | Aug 31 2026, 06:33 PM |
|
Standing down on the Workers Builds: trenova failure: this PR touches only Go code in All repository CI on this head (Lint, Build, Unit Tests, Integration Tests, Codegen Checks) is green. Generated by Claude Code |
Description
The WAL decoder already emitted TRUNCATE records, but no sink handled them. A
TRUNCATEon a projected table had two failure modes: the Meilisearch sink could not derive a document key from the data-less record, so every truncate burned its retries and landed in the DLQ; the Redis JSON sink fell through toJSON.SETwith a key rendered from empty placeholders. Either way, all previously projected documents and cache keys stayed behind as stale data.Per-sink handling now:
DeleteDocumentsByFilteron the_projection/_source_tablemetadata every document already carries. Those two fields are now always registered as filterable (previously filterable attributes were only configured when the projection declared some), which also makes the delete correct if two projections ever share an index.*, literal text is glob-escaped,.Schema/.Tablerender normally) and deletes matching keys viaSCAN+ batchedUNLINK. A pattern with no literal content is refused outright, so a misconfigured all-placeholder template can never scan-and-delete the entire keyspace.Related Issue or Discussion
Follow-up from the codebase audit driving PRs #557–#563 (gtc reliability slice).
Type of Change
Scope
services/gtc/internal/adapters/secondary/redis/template.go— wildcard-pattern rendering with glob escaping and the no-literal-anchor guardservices/gtc/internal/adapters/secondary/redis/sink.go— truncate branch in the JSON sink (SCAN+ batchedUNLINK), template cache refactorservices/gtc/internal/adapters/secondary/meilisearch/sink.go— truncate branch (delete-by-filter), always-filterable metadata fieldsgo.mod/go.sumaddminiredis(test-only)Validation
cd services/gtc && go build ./... && go vet ./... && go test ./...— all greengofmt -lclean; new lines hand-checked against the 100-column golines budgetcd services/tms && task test/task lint— not run; no TMS changescd client && pnpm build/pnpm lint— not run; no client changesDeployment Notes
_projection/_source_table, which triggers a one-time reindex task per index.github.com/alicebob/miniredis/v2(the repo had no Redis fake; the truncate path is a destructive glob delete and is now covered end to end).Checklist
AGENTS.md,CLAUDE.md, and existing repository patterns.🤖 Generated with Claude Code
https://claude.ai/code/session_015houJkqb8SuqPW4YpLoWCq
Generated by Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Tests