Skip to content

feat: integrate PR 5450 review specs and implementation - #10

Open
yokoszn wants to merge 7 commits into
review/pr5450-basefrom
integrate/pr5450-review-and-implementation
Open

yokoszn wants to merge 7 commits into
review/pr5450-basefrom
integrate/pr5450-review-and-implementation

Conversation

@yokoszn

@yokoszn yokoszn commented Aug 24, 2026

Copy link
Copy Markdown

PR 5450 integration candidate

This branch integrates the two review lanes onto the current PR open-mercato#5450 base (60e0bac3b7):

  • PR 8 documentation/spec complexity and verification changes.
  • PR 9 repair-cell implementation, leases, data-sync wiring, queue recovery, fencing, and reversible migrations.

Validation

  • Core typecheck passed.
  • Focused repair-cell tests: 3/3.
  • Local queue strategy tests: 35/35.
  • Queue package build and core build passed on the source branches.
  • Full queue suite: 104/104 with --forceExit; normal Jest shutdown still has an open-handle cleanup gate.

This is an integration candidate for review, not a direct mutation of the upstream PR branch. The remaining live Postgres concurrent-claim/crash-recovery, Valkey worker-loss, workflow latency/RSS, and full upstream validation gates remain explicit.

@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5aaa201e-1043-461a-a5b6-f36474ac0181

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d8e67707a8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +5 to +6
const em = { upsert: jest.fn().mockResolvedValue(undefined) }
await recordDataSyncRepairCell(em as never, 'progress-1', { tenantId: 'tenant-1', organizationId: 'org-1' }, 'import', 'upstream timeout')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Mock getConnection in the repair-cell test

This test constructs an entity manager with only upsert, but recordDataSyncRepairCell() delegates to upsertRepairCell(), which calls em.getConnection().execute(...). Consequently, running this new test throws TypeError: em.getConnection is not a function before reaching the assertion; mock the connection API and assert the executed statement instead.

Useful? React with 👍 / 👎.

Comment on lines 641 to +643
queueWatcher = watcher
queueWatcherIdentity = nextIdentity
watcherRetryAttempts = 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not reset retries before the watcher proves stable

When fs.watch() returns a watcher but that watcher subsequently emits a persistent error, every retry successfully constructs another watcher and resets watcherRetryAttempts here before the next error. The error handler therefore never reaches the three-attempt limit, producing an unbounded 100 ms re-arm and logging loop in exactly the asynchronous watcher-error scenario this recovery path handles; reset the counter only after a stable period or preserve the accumulated error count across re-arms.

Useful? React with 👍 / 👎.

Comment on lines +672 to +673
queueDirectoryProbe = setInterval(() => {
void fsp.stat(queueDir).then(() => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop probing healthy queue directories every 100 ms

Every continuous local worker now starts this interval permanently, so even with a healthy watcher and an idle queue it performs ten filesystem stat calls per second per queue. A worker --all process therefore creates continuous filesystem load proportional to the number of queues, contradicting the accompanying recovery design that limits probes to periods when the directory is absent or the watcher is unavailable; arm the fast probe only during recovery and stop it after the watcher is restored.

Useful? React with 👍 / 👎.

Comment on lines +45 to +48
"lease_epoch" = excluded."lease_epoch",
"reason" = excluded."reason",
"updated_at" = now()
where excluded."lease_epoch" >= "progress_job_repair_cells"."lease_epoch"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Revoke old claims when upserting a newer repair epoch

When an upsert with an equal or newer leaseEpoch is accepted while the cell is already leased, this update replaces the cell's due time and reason but leaves the previous lease_token and lease_until intact. The worker holding that old token can then call acknowledgeRepairCell() and delete the newly recorded repair condition, so a failure that races with an active repair is lost; invalidate the old lease on an accepted replacement or include the epoch in acknowledgement and release predicates.

Useful? React with 👍 / 👎.

Comment on lines +46 to +48
const syncRunService = ctx.resolve<SyncRunService>('dataSyncRunService')
const run = await syncRunService.getRun(job.payload.runId, job.payload.scope)
await clearDataSyncRepairCell(em, run?.progressJobId, job.payload.scope)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Clear the repair cell only after a recovered run

On a queue retry after this handler has marked the run failed, runImport() can resolve the transient dependency and then return early because its failed → running transition matches zero rows. The worker nevertheless reloads that still-failed run and clears its repair cell, so the delivery is reported successful and the only repair marker disappears without the sync being rerun; verify that the run actually reached the intended recovered/terminal state before clearing the cell. The export worker contains the same sequence.

Useful? React with 👍 / 👎.

Comment on lines +55 to +58
const em = ctx.resolve<import('@mikro-orm/postgresql').EntityManager>('em')
const progressService = ctx.resolve<ProgressService>('progressService')
const run = await syncRunService.getRun(job.payload.runId, job.payload.scope)
await recordDataSyncRepairCell(em, run?.progressJobId, job.payload.scope, 'import', message)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not let repair-cell writes block terminal finalization

If the new repair table is unavailable—for example during schema drift or a rolling deployment—or its conditional upsert otherwise fails, this awaited auxiliary write aborts the entire nested finalization block before markStatus(..., 'failed') and progressService.failJob() run. Every retry can therefore leave both the sync run and its progress job non-terminal solely because diagnostic repair bookkeeping failed; isolate/log the repair-cell error and always execute the existing terminal transitions. The export worker has the same ordering.

AGENTS.md reference: packages/core/src/modules/progress/AGENTS.md:L7-L10

Useful? React with 👍 / 👎.

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