fix(query): refresh namespace-filtered synced queries on deep CRUD (catalog Removed on delete)#295
Open
rbuergi wants to merge 1 commit into
Open
fix(query): refresh namespace-filtered synced queries on deep CRUD (catalog Removed on delete)#295rbuergi wants to merge 1 commit into
rbuergi wants to merge 1 commit into
Conversation
…atalog Removed on delete)
The reactive change-feed relevance filter (PostgreSqlMeshQuery) asked PathMatcher.ShouldNotify(
changedPath, BasePath, Scope) — a PATH check. The 'open threads' catalog queries by NAMESPACE
(namespace:{owner}/*_Thread, no path:) → empty BasePath → Scope degraded to 'direct children of
root'. A thread deleted 3 levels deep at {owner}/_Thread/{id} was judged out of scope → no
re-query → the catalog kept showing the deleted thread (and never showed new ones / dropped
Done ones).
Fix — ask the broadcast event if it's in the query's scope by NAMESPACE too, not just path
(the user's Service-Broker-style 'check in-scope → refresh'):
• PathMatcher.ShouldNotifyForQuery(path, base, scope, namespaces) = ShouldNotify OR the changed
node's namespace (path minus last segment) matches a query namespace (wildcard-aware).
• ParsedQuery.ExtractNamespacePatterns() collects namespace Like/glob patterns too (ExtractNamespaces
stays concrete-only for aggregator routing, which can't route a glob). The parser rewrites the
user's * → SQL-LIKE %, so the matcher accepts either.
• PostgreSqlMeshQuery captures the patterns per filter and uses ShouldNotifyForQuery in both the
early + live change subscriptions.
PG broadcast events carry only the path (pg_notify sends the key, not the row), so the in-scope
test is path/namespace-based; the subsequent re-query applies the content filters (nodeType, status).
Pure logic → fully unit-tested: QueryChangeRelevanceTest drives Created/Updated/Deleted for an
in-scope thread + out-of-scope negatives (10/10). No Postgres needed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Task #10 — the start-page "Open threads" catalog didn't refresh after deleting a thread.
Root
The reactive change-feed relevance filter asks
PathMatcher.ShouldNotify(changedPath, BasePath, Scope)— a path check. The catalog queries by namespace (namespace:{owner}/*_Thread, nopath:), soBasePathis empty andScopedegrades to "direct children of root". A thread deleted 3 levels deep at{owner}/_Thread/{id}is judged out of scope → no re-query → noRemoved→ the deleted thread lingers (and new/Done ones don't update either).Fix (your Service-Broker-style "check in-scope → refresh")
Ask the broadcast CRUD event whether it's in the query's scope by namespace, not just path:
PathMatcher.ShouldNotifyForQuery(path, base, scope, namespaces)=ShouldNotifyOR the changed node's namespace (path minus last segment) matches a query namespace (wildcard-aware).ParsedQuery.ExtractNamespacePatterns()collects the namespace glob patterns too (ExtractNamespacesstays concrete-only for aggregator routing, which can't route a glob). The parser rewrites the user's*→ SQL-LIKE%, so the matcher accepts either.PostgreSqlMeshQuerycaptures the patterns and uses the new predicate in both the early + live change subscriptions.PG broadcast events carry only the path (pg_notify sends the key, not the row), so the in-scope test is path/namespace-based; the subsequent re-query applies the content filters (
nodeType,status).Tests
Pure logic → fully unit-tested, no Postgres.
QueryChangeRelevanceTestdrives Created / Updated / Deleted for an in-scope thread + out-of-scope negatives (non-thread same partition, different partition) + the namespace glob — 10/10 green,-warnaserrorclean.🤖 Generated with Claude Code