Repository navigation
Doc: the storage-side Durable-But-Unreadable mechanism, reproduced, plus the sweep for the rows already lost (#4513) - #4562
Merged
Conversation
…nd the sweep for the ones already out there (#4513) A second producer of the three-seam signature lived in the Postgres backend and is now fixed in MeshWeaver.Plugins: the write resolved its table from (path, nodeType) while every read resolves it from the path alone, so a node whose NodeType maps to a satellite table but whose PATH carries no satellite segment was written where no reader looks - acknowledged, versioned, invisible. It is the first instance of this class that reproduces on demand, in a test. Also records two things the code settles for free: - changed_by on a mesh_node_history row says WHICH writer produced it. The trigger is on mesh_nodes only and copies last_modified_by; the app-side WriteVersion binds none. So a stamped row proves a committed mesh_nodes row of that version - which exonerates the write path for the third instance and moves its open question to what removed the row. - an EQUAL-version write applies and the history trigger's ON CONFLICT DO NOTHING records nothing, so get_version <max> is the last DISTINCT version, not necessarily the current row. And documents the sweep that finds the instances already in production rather than one at a time: DurableButUnreadableDetector compares a partition's node tables against its version store, as the system, and classifies each row it cannot reconcile - holding deleted nodes apart from lost ones. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
Doc-only change with passing documentation tests; remaining feedback is a small documentation formatting fix (table header clarity).
Pull request overview
Updates the “Durable But Unreadable” architecture doc to record the now-identified PostgreSQL storage-side mechanism (and its fix in MeshWeaver.Plugins), plus how to detect already-affected rows and what the evidence implies for the third confirmed instance (#4513).
Changes:
- Document the storage-table routing asymmetry (write:
(path,nodeType)vs read:path) and the two-part fix strategy (placement + unconfirmed-write handling). - Clarify what the history
changed_bystamp proves for the third instance, and what remains unexplained. - Add the recommended sweep approach (
DurableButUnreadableDetector) and how to run it operationally.
File summaries
| File | Description |
|---|---|
| src/MeshWeaver.Documentation/Data/Architecture/DurableButUnreadable.md | Adds storage-side mechanism + detection sweep guidance; updates “Open” section based on new evidence for #4513. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| Each seam then answers exactly as the three-seam test describes: | ||
|
|
||
| | Seam | Why it misses | | |
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
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.
Doc-only. Records the storage-side mechanism of the class this page defines — found in code,
reproduced deterministically, and fixed in
MeshWeaver.Plugins#1998 —
plus two things the code settles about the third instance for free, and the sweep for the instances
already in production.
From #4513.
The mechanism, and it reproduces on demand
PostgreSqlStorageAdapterresolved a WRITE's table from(path, nodeType)and every READ's tablefrom the
pathalone — a reader only ever has a path. So a node whose NodeType maps to asatellite table but whose PATH carries no satellite segment (a
Comment,Thread,Notification,Activity, … filed at an ordinary path) went into the satellite table whileRead,ReadMany,Exists,ListChildPaths,ListDescendantPaths,FindBestPrefixMatchandDeleteManyall looked in
mesh_nodes. The version store is matched on the storedpathcolumn and is nottable-routed, so the history row lands regardless — index absent, point read absent, version store
present, and the write reports success twice over.
DurableButUnreadableTest(MeshWeaver.Plugins) is the first repro of this class: measured onorigin/main4 of 4 satellite-typed cases fail with the acknowledgement in hand and the versionrow written; after the fix 8 of 8 pass. Every pre-existing satellite test writes to a path that
already contains the segment, where the two resolutions agree by construction — the asymmetry lived
in the argument, so no test that never varied it could see it.
Two things the code settles for free
changed_bynames the writer.mesh_node_copy_to_historyis installed onmesh_nodesONLYand copies
last_modified_by; the app-sidePostgreSqlVersionQuery.WriteVersionbinds nochanged_byat all. A stamped history row therefore PROVES a committedmesh_nodesrow of thatversion. All 53 of
Deployments/client-b-provision-20260914's rows carrysystem-security, so itsrow was in
deployments.mesh_nodeswithmain_node == pathandstate: Activeatv62(
get_version … 62, measured 2026-09-17 on memex.systemorph.com). The write path is exonerated byits own evidence; Durable But Unreadable: a third confirmed instance — Deployments/client-b-provision-20260914 has 53 version rows and no readable current row (Plugins#1922 half 2) #4513's open question moves to what REMOVED or replaced the row.
design (
WHERE target.version <= EXCLUDED.version) while the history trigger isON CONFLICT (namespace, id, version) DO NOTHING, so a same-version write replaces content,stateandmain_nodeand records nothing.Finding the ones already out there
DurableButUnreadableDetectorcompares a partition's node tables against its version store, readsthem directly as the system (so its denominator is the partition, not a caller's grants) and
classifies every row it cannot reconcile —
MisplacedRow,AcknowledgedButAbsent,RemovedAfterCommit(what a DELETE looks like, held apart on evidence) andRowBehindItsHistory—with the denominators travelling alongside. Read-only; the repair of an existing row is a decision
about content, not a mechanical one.
Verification
dotnet build test/MeshWeaver.Documentation.Test/MeshWeaver.Documentation.Test.csproj -c Release -warnaserror→ 0 Warning(s), 0 Error(s).
MeshWeaver.Documentation.Test(incl.DocumentationLinkIntegrityTest) → 505 total, 0 failed.No public surface change, no i18n key, no package version —
Pairs-with,Implementers,Satellite-pinsandMirror-syncdo not apply to a doc-only diff.🤖 Generated with Claude Code