Skip to content

fix(sync): don’t re-push soft-deletes or restores - #11055

Open
jaskfla wants to merge 18 commits into
mainfrom
tam-7120-1-persist-pulled-deletes-with-sentinel
Open

jaskfla wants to merge 18 commits into
mainfrom
tam-7120-1-persist-pulled-deletes-with-sentinel

Conversation

@jaskfla

@jaskfla jaskfla commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Records pulled from central are marked with the INCOMING_FROM_CENTRAL_SERVER sentinel (-1) so the set_updated_at_sync_tick trigger stores them as LAST_UPDATED_ELSEWHERE (-999) and the facility never pushes them back. saveDeletes, saveRestores and the soft-delete branch of saveCreates used paranoid destroy()/restore(), which leave updated_at_sync_tick out of the statement, so the trigger stamped the current tick instead and every facility echoed central's own deletes straight back to it (a ~800k-row bulk delete on central produced an equal-sized push from the facility that pulled it).

Write deleted_at and the tick in the same statement. On central the incoming records carry no tick, so behaviour there is unchanged.

Changes

Add a brief description of the changes in this PR to help give the reviewer context.

Auto-Deploy

  • Deploy
Options
  • Artillery load test
  • Seed from closest snapshot
  • Generate fake data
  • More data (20Gi)
  • No facility servers (central-only)
  • No sync (facility tasks scaled to zero)
  • Skip mobile build
  • Always build mobile
  • Stay up for 8 hours
  • Stay up for 24 hours
  • Stay up (no TTL)
  • Build images only (don't deploy)
  • Build all images (amd64 + Windows; default is arm64 only)
  • Pause this deploy

Tests

  • Run E2E tests
  • Run DAST scan

Review Hero

  • Run Review Hero
  • Auto-fix review suggestions Wait for Review Hero to finish, resolve any comments you disagree with or want to fix manually, then check this to auto-fix the rest.
  • Auto-fix CI failures Check this to auto-fix lint errors, test failures, and other CI issues.
  • Auto-merge upstream Check this to merge the base branch into this PR, with AI conflict resolution if needed.
  • Save suppressions Check this to capture 👎 reactions on Review Hero comments as suppression rules in .github/review-hero/suppressions.yml. Also runs automatically at the end of any auto-fix run.

Remember to...

  • ...write or update tests
  • ...add UI screenshots and testing notes to the Linear issue
  • ...add any manual upgrade steps to the Linear issue
  • ...update the config reference, settings reference, or any relevant runbook(s)
  • ...call out additions or changes to config files for the deployment team to take note of

@jaskfla
jaskfla force-pushed the tam-7120-1-persist-pulled-deletes-with-sentinel branch from d56886c to bdcd99a Compare September 10, 2026 04:18
@review-hero

review-hero Bot commented Sep 10, 2026

Copy link
Copy Markdown

🦸 Review Hero Summary (round 1)
9 agents reviewed this PR | 0 critical | 0 suggestions | 0 nitpicks | Filtering: consensus 3 voters, 1 below threshold

No issues found. Looks good!

Below consensus threshold (1 unique issue not confirmed by majority)
Location Agent Severity Comment
packages/database/src/sync/saveChanges.ts:50 Bugs & Correctness suggestion new Date() is evaluated once per record inside the loop, so soft-deleted records created in the same sync batch can end up with slightly different deletedAt timestamps. This is inconsistent wit...

@jaskfla
jaskfla force-pushed the tam-7120-1-persist-pulled-deletes-with-sentinel branch 2 times, most recently from abf13d2 to d57fbed Compare September 10, 2026 05:40
@jaskfla jaskfla changed the title fix(sync): don’t re-push soft-deletes fix(sync): don’t re-push soft-deletes & restores Sep 10, 2026
@jaskfla jaskfla changed the title fix(sync): don’t re-push soft-deletes & restores fix(sync): don’t re-push soft-deletes or restores Sep 10, 2026
@jaskfla
jaskfla force-pushed the tam-7120-1-persist-pulled-deletes-with-sentinel branch from 88f0733 to f7b198a Compare September 10, 2026 21:57
@jaskfla
jaskfla marked this pull request as ready for review September 10, 2026 22:35
@jaskfla
jaskfla force-pushed the tam-7120-1-persist-pulled-deletes-with-sentinel branch 2 times, most recently from 0a3db27 to 75df0ab Compare September 11, 2026 04:58
…tinel

Records pulled from central are marked with the INCOMING_FROM_CENTRAL_SERVER
sentinel (-1) so the set_updated_at_sync_tick trigger stores them as
LAST_UPDATED_ELSEWHERE (-999) and the facility never pushes them back.
saveDeletes, saveRestores and the soft-delete branch of saveCreates used
paranoid destroy()/restore(), which leave updated_at_sync_tick out of the
statement, so the trigger stamped the current tick instead and every facility
echoed central's own deletes straight back to it (a ~800k-row bulk delete on
central produced an equal-sized push from the facility that pulled it).

Write deleted_at and the tick in the same statement. On central the incoming
records carry no tick, so behaviour there is unchanged.
Every existing record in a sync payload already goes through saveUpdates, so
saveDeletes/saveRestores were a second statement per batch that only flipped
deleted_at. Carrying the delete/restore decision on the update payload writes
deleted_at, the field changes and updated_at_sync_tick in a single statement
per record, and removes setDeletedAt, saveDeletes and saveRestores.

On central the incoming record is merged field by field using
updated_at_by_field, which does not track deleted_at, so the merge would keep
the existing value and drop the delete. deleted_at is kept out of the merge
and the caller's decision applied afterwards.
@jaskfla
jaskfla force-pushed the tam-7120-1-persist-pulled-deletes-with-sentinel branch from 75df0ab to 56a516f Compare September 15, 2026 01:59
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.

1 participant