Skip to content

fix(community): skip purged comments in postUpdates MFS sync#143

Merged
Rinse12 merged 1 commit into
masterfrom
fix/purge-postupdates-sync-race
Jun 13, 2026
Merged

fix(community): skip purged comments in postUpdates MFS sync#143
Rinse12 merged 1 commit into
masterfrom
fix/purge-postupdates-sync-race

Conversation

@Rinse12

@Rinse12 Rinse12 commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Problem

A TOCTOU race between comment purge and the postUpdates MFS sync can leave a purged post's CommentUpdate permanently in a community's postUpdates MFS tree.

syncIpnsWithDb (sync loop) and storeCommentModeration (pubsub challenge handler) run concurrently with no mutual exclusion:

  1. A sync cycle calculates a post's CommentUpdate (post still in DB), producing a row with localMfsPath = /<addr>/postUpdates/<bucket>/<postCid>/update.
  2. A purge moderation arrives: the post is deleted from the DB, its MFS path is queued and removed (rmUnneededMfsPaths, which also drains _mfsPathsToRemove).
  3. The in-flight sync from step 1 reaches syncPostUpdatesWithIpfs and writes the captured (pre-purge) row back to MFS.

Because the post is now gone from the DB it is never recalculated or re-purged, and nothing scans the MFS tree against the DB (calculateNewPostUpdates only reads bucket dirs), so the resurrected entry persists indefinitely.

This surfaced as a flaky failure in the remote-libp2pjs CI config (the slower client transport widens the timing window so the purge lands mid-sync); the Kubo-RPC / gateway configs run the same community-side code and pass:

AssertionError: MFS path /<community>/postUpdates/86400/<postCid>/update still exists after 30s - purge cleanup did not complete
  at test/node-and-browser/publications/comment-moderation/purged.test.ts:292

Fix

syncPostUpdatesWithIpfs now filters out post-update rows whose comment no longer exists in the DB (new lightweight DbHandler.commentExistsInDb(cid)) before writing to MFS. A row captured before a mid-cycle purge is skipped instead of resurrecting the purged post. When every captured post was purged, it writes nothing instead of throwing.

Test

test/node/community/purge-postupdates-sync-race.test.ts drives the exact racy ordering (capture row -> purge -> stale sync write) and asserts the purged post is not resurrected in MFS. It is red against unmodified src/ and green with the fix. The happy-path local.publishing.community.test.ts (posting -> postUpdates sync) still passes.

Fixes #142

Summary by CodeRabbit

  • Bug Fixes

    • Fixed a race condition that could cause deleted comments to be incorrectly restored during synchronization operations.
  • Tests

    • Added integration tests for comment purge and synchronization workflows.

A sync cycle can capture a post's CommentUpdate while the post is still
live, then a concurrent purge (storeCommentModeration) deletes the post
from the DB and removes its postUpdates MFS entry. The in-flight sync
then wrote the captured update back to MFS, resurrecting the purged post
permanently — it is gone from the DB, so nothing ever cleans it up again.

syncPostUpdatesWithIpfs now filters out post-update rows whose comment no
longer exists in the DB (new DbHandler.commentExistsInDb) before writing,
so a row captured before a mid-cycle purge is skipped instead of
resurrecting the post.

Adds a deterministic regression test driving the capture -> purge ->
stale-write ordering.

Fixes #142
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR fixes a race condition where purged posts could be resurrected in IPFS MFS during concurrent sync operations. A new database existence check enables the sync path to filter out stale updates, and a regression test validates the fix.

Changes

Purge vs PostUpdates Sync Race Fix

Layer / File(s) Summary
Comment existence check in database
src/runtime/node/community/db-handler.ts
New commentExistsInDb(cid) method queries the comments table with SELECT 1 LIMIT 1 to check comment existence.
Sync filtering for purged comments
src/runtime/node/community/local-community/comment-updates.ts
syncPostUpdatesWithIpfs re-checks each captured update's existence in the DB before writing to MFS, filters out purged comments, logs the skip count, and updates the sync log to report only live updates.
Regression test for race condition
test/node/community/purge-postupdates-sync-race.test.ts
New Vitest integration test reproduces the TOCTOU race: publishes a post, captures its comment update, purges the post (removing its MFS entry), then invokes sync with the pre-purge row and asserts the entry is not resurrected. Includes an mfsPathExists helper.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main fix: preventing purged comments from being synced to the MFS postUpdates tree, which is the core objective of the PR.
Linked Issues check ✅ Passed The PR fully addresses all coding objectives from issue #142: adds deterministic regression test, implements the fix to skip purged comments in syncPostUpdatesWithIpfs, and validates with existing tests.
Out of Scope Changes check ✅ Passed All changes directly address the TOCTOU race: new commentExistsInDb method, filtering logic in syncPostUpdatesWithIpfs, and regression test. No extraneous modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/purge-postupdates-sync-race

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Rinse12 Rinse12 merged commit 8b68b7f into master Jun 13, 2026
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Purge vs postUpdates sync race: in-flight sync resurrects a purged post's MFS entry

1 participant