Repository navigation
Conversation
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
[Medium impact] The PR appears safe to merge; no actionable issues were found.
|
…er its save A parent rename now waits for any save of its descendants in flight: moveDescendants first locks them in FOR NO KEY UPDATE mode, top down and the item itself excluded, then rebuilds their addresses from what they hold after it.
7b0ea4d to
dd0ffa8
Compare
Code Review ✅ Approved🔴 High risk · Locking descendants before rebuilding paths changes stored page-address integrity; coordination issues could leave nested pages with stale or mismatched addresses. Fixes a parent rename building child addresses from a stale slug by locking all descendants with VerificationRules No rules evaluated Functional validation Not enabledFor more verification details, comment OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source |
There was a problem hiding this comment.
Gates Failed
Enforce critical code health rules
(1 file with Low Cohesion)
Our agent can fix these. Install it.
Gates Passed
2 Quality Gates Passed
Reason for failure
| Enforce critical code health rules | Violations | Code Health Impact | |
|---|---|---|---|
| content_nesting_lock_test.go | 1 critical rule | 10.00 → 8.82 | Suppress |
Quality Gate Profile: Clean Code Collective
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.
A parent rename rebuilt its children's addresses from what it read before a child's save in flight had finished.
MoveDescendantscomputes each new path in a recursive CTE and then updates the rows in the same statement. When a child's save holds that child's row, the UPDATE waits for it, but under READ COMMITTED PostgreSQL then re-checks only the updated row, not the CTE, so the path it writes is built from the child's old slug. Both saves succeed and the child's slug and address disagree.moveDescendantsnow first locks every descendant with a newLockDescendantsquery, then runsMoveDescendants, which starts with a fresh snapshot and reads each child as it stands after its save. This is the order proposed in the issue: the rename waits for its children's saves, then builds their addresses from what they hold. The rows are locked from the top down (depth, then id), so a parent rename waiting on a child holds none of that child's descendants. The lock is taken inFOR NO KEY UPDATEmode, the mode the existing rewrite takes when the paths do not change, so an edit that keeps the address still does not wait for a page being filed under a child; it does conflict with a child's own save, which is the point.Before, in the new test: the child saved under the slug
teamwhile its parent was renamed tomanualended atpages/manual/about. After:pages/manual/team.Testing: three tests in
content_nesting_lock_test.go. The first, run for a child save and for a grandchild save, fails on main in both cases. The second pins the top down order (it fails if the rows are locked by id only), the third the lock mode (it fails underFOR UPDATE).go test -race ./internal/postgres/passes and the three tests pass 20 runs in a row. Against PostgreSQL 18,go test ./...shows no new failure: the packages that fail here fail on main too (two flaky same-timestamp checks and two tests that depend on the local machine).golangci-lint run(both modules) andgo run ./cmd/doclintreport nothing.Not covered: a page filed under a child (created or moved there) during a parent rename can still keep the old address, since filing takes only a key share lock on the child. That window predates this change and concerns a page joining the subtree, not a descendant's own save, so I left it out.
Fixes #510
Summary by CodeRabbit