Skip to content

TaskScheduler: include the bucket and the eTag in the action dedupe key - #2798

Merged
bert-e merged 3 commits into
development/9.6from
bugfix/BB-810/task-scheduler-dedupe-key
Aug 28, 2026
Merged

TaskScheduler: include the bucket and the eTag in the action dedupe key#2798
bert-e merged 3 commits into
development/9.6from
bugfix/BB-810/task-scheduler-dedupe-key

Conversation

@delthas

@delthas delthas commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

The TaskScheduler dedupe key of an ActionQueueEntry omitted the bucket, so two actions targeting the same object key in different buckets were considered duplicates and the second one was silently dropped — it is acknowledged and its offset committed, so nothing replays it.

Two changes, in this order:

1. A distinct task scheduler for the data mover. A queue processor pushed the entries of both its consumers into one scheduler — replication entries from the replication topic (QueueProcessor.js:936) and copyLocation actions from the data-mover topic (:993) — so entries of the two kinds serialized on the same queue key and, worse, deduplicated against each other, although they are distinct work. Each consumer now gets its own. Note this also means a replication entry and a copyLocation on the same bucket/key are no longer serialized against each other; that guard was weak, as _applyTransitionRule already skips objects whose replication status is PENDING/PROCESSING/FAILED.

2. The dedupe key itself. What it is made of, before and after:

Component Before After Why
bucket no yes The object key alone is not unique: index.html in two buckets gave the same key, and the second action was dropped.
object key yes yes
version yes yes Identifies the object version — but is undefined for objects in non-versioned buckets, hence the eTag below.
eTag read contentMd5, always undefined yes No producer has ever set target.contentMd5, in any version: the content of a copyLocation action is carried by target.eTag, so that component was dead and the read is now gone. Without it bucket/key is a mutable identity — a non-versioned object overwritten between two scans collides with its own pending action, and the pending one then fails CopyLocationTask._checkObjectState (:845-853) with "object contents have changed", so neither action transitions the object. Quotes are stripped so the same content always yields the same key.
toLocation no no Not needed: processDataMoverEntry only builds a task when toLocation === this.site (:980), so it is constant within a given scheduler.

The ObjectQueueEntry branch is unchanged: it already carried the bucket (via getCanonicalKey()) and a real contentMd5.

Nothing to migrate: a dedupe cache is per scheduler and in-memory, cleared when the task ends, and the key is derived from attributes already published.

Tasks skipped by deduplication are now logged, which was so far silent. The logger takes the constructor slot of a concurrency parameter that TaskScheduler never had — that limit is enforced by the consumer, in BackbeatConsumer._getAvailableSlotsInPipeline().

Follow-up in BB-855: rather than letting a stale action run and fail its state check, deduplication could replace the queued task with the newer one and keep only the most up-to-date message. That needs TaskScheduler to support replacing a queued task, which it cannot do today.

Issue: BB-810

@bert-e

bert-e commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Hello delthas,

My role is to assist you with the merge of this
pull request. Please type @bert-e help to get information
on this process, or consult the user documentation.

Available options
name description privileged authored
/after_pull_request Wait for the given pull request id to be merged before continuing with the current one.
/bypass_author_approval Bypass the pull request author's approval
/bypass_build_status Bypass the build and test status
/bypass_commit_size Bypass the check on the size of the changeset TBA
/bypass_incompatible_branch Bypass the check on the source branch prefix
/bypass_jira_check Bypass the Jira issue check
/bypass_peer_approval Bypass the pull request peers' approval
/bypass_leader_approval Bypass the pull request leaders' approval
/approve Instruct Bert-E that the author has approved the pull request. ✍️
/create_pull_requests Allow the creation of integration pull requests.
/create_integration_branches Allow the creation of integration branches.
/no_octopus Prevent Wall-E from doing any octopus merge and use multiple consecutive merge instead
/unanimity Change review acceptance criteria from one reviewer at least to all reviewers
/wait Instruct Bert-E not to run until further notice.
Available commands
name description privileged
/help Print Bert-E's manual in the pull request.
/status Print Bert-E's current status in the pull request.
/clear Remove all comments from Bert-E from the history TBA
/retry Re-start a fresh build TBA
/build Re-start a fresh build TBA
/force_reset Delete integration branches & pull requests, and restart merge process from the beginning.
/reset Try to remove integration branches unless there are commits on them which do not appear on the source branch.

Status report is not available.

@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.57%. Comparing base (225a8a3) to head (94795a3).

Additional details and impacted files

Impacted file tree graph

Files with missing lines Coverage Δ
...sions/replication/queueProcessor/QueueProcessor.js 75.41% <100.00%> (+0.13%) ⬆️
...replication/queueProcessor/taskSchedulerHelpers.js 89.47% <100.00%> (+0.58%) ⬆️
lib/BackbeatConsumer.js 94.66% <ø> (-0.25%) ⬇️
lib/tasks/TaskScheduler.js 100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes

Components Coverage Δ
Bucket Notification 80.27% <ø> (ø)
Core Library 81.45% <100.00%> (-0.49%) ⬇️
Ingestion 70.09% <ø> (ø)
Lifecycle 80.46% <ø> (ø)
Oplog Populator 85.83% <ø> (ø)
Replication 62.09% <100.00%> (+0.04%) ⬆️
Bucket Scanner 85.76% <ø> (ø)
@@                 Coverage Diff                 @@
##           development/9.6    #2798      +/-   ##
===================================================
- Coverage            75.77%   75.57%   -0.20%     
===================================================
  Files                  200      200              
  Lines                13922    13927       +5     
===================================================
- Hits                 10549    10526      -23     
- Misses                3363     3391      +28     
  Partials                10       10              
Flag Coverage Δ
api:retry 9.10% <0.00%> (-0.01%) ⬇️
api:routes 8.87% <0.00%> (-0.01%) ⬇️
bucket-scanner 85.76% <ø> (ø)
ft_test:queuepopulator 10.14% <8.33%> (-0.90%) ⬇️
ingestion 12.26% <0.00%> (-0.01%) ⬇️
lib 8.82% <8.33%> (-0.01%) ⬇️
lifecycle 19.31% <8.33%> (-0.01%) ⬇️
notification 1.02% <0.00%> (-0.01%) ⬇️
oplogPopulator 0.13% <0.00%> (-0.01%) ⬇️
replication 18.87% <91.66%> (+0.02%) ⬆️
unit 54.97% <91.66%> (+0.08%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@scality scality deleted a comment from bert-e Aug 14, 2026
@bert-e

bert-e commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Waiting for approval

The following approvals are needed before I can proceed with the merge:

  • the author

  • 2 peers

@delthas
delthas force-pushed the bugfix/BB-810/task-scheduler-dedupe-key branch 2 times, most recently from dc3d703 to e307e22 Compare August 14, 2026 15:18
@delthas
delthas requested review from a team, DarkIsDude and francoisferrand August 14, 2026 15:21
Comment thread extensions/replication/queueProcessor/taskSchedulerHelpers.js Outdated
Comment thread extensions/replication/queueProcessor/taskSchedulerHelpers.js Outdated
Comment thread extensions/replication/queueProcessor/taskSchedulerHelpers.js
Comment thread extensions/replication/queueProcessor/taskSchedulerHelpers.js
Comment thread extensions/replication/queueProcessor/taskSchedulerHelpers.js
Comment thread extensions/replication/queueProcessor/taskSchedulerHelpers.js Outdated
Comment thread extensions/replication/queueProcessor/taskSchedulerHelpers.js Outdated
Comment thread lib/BackbeatConsumer.js
Comment thread extensions/replication/queueProcessor/taskSchedulerHelpers.js Outdated
@scality scality deleted a comment from bert-e Aug 19, 2026
@DarkIsDude

Copy link
Copy Markdown

Reading back Francois review, whats happens with old data and new data ? I mean, can we have conflicts and/or dedup not working because the key changes at deployment time ?

@delthas
delthas force-pushed the bugfix/BB-810/task-scheduler-dedupe-key branch 2 times, most recently from 77767b3 to 04da66b Compare August 19, 2026 17:29
@delthas

delthas commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

whats happens with old data and new data ? I mean, can we have conflicts and/or dedup not working because the key changes at deployment time ?

No conflict is possible: the dedupe cache is per-process and in-memory, and it only holds tasks that are currently queued or in flight. Keys are computed at push time, from the message, by whichever process consumes it — they are never persisted, and never compared between processes. A process that restarts or is upgraded starts with an empty cache.

Mixed producer versions are not a problem either. Nothing has ever written target.contentMd5 — zero occurrences in ReplicationAPI.js on 7.70, 8.6, 9.0 and 9.5, and git log --all -S"contentMd5" on that file returns no commit — so there is no legacy message shape to be compatible with, and the fields the key now uses (bucket, key, version, eTag) have always been published by createCopyLocationAction.

The worst case during a rolling upgrade is that an old and a new process each deduplicate within their own window, so a duplicate pair could be processed twice instead of once. That is the at-least-once behaviour the pipeline already handles: CopyLocationTask._checkObjectState skips an object that has already been transitioned.

@scality scality deleted a comment from bert-e Aug 19, 2026
@bert-e

bert-e commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Request integration branches

Waiting for integration branch creation to be requested by the user.

To request integration branches, please comment on this pull request with the following command:

/create_integration_branches

Alternatively, the /approve and /create_pull_requests commands will automatically
create the integration branches.

@scality scality deleted a comment from bert-e Aug 19, 2026
@delthas
delthas changed the base branch from development/9.5 to development/9.6 August 20, 2026 08:54
@delthas
delthas force-pushed the bugfix/BB-810/task-scheduler-dedupe-key branch from 04da66b to 56026f5 Compare August 20, 2026 08:54
@delthas delthas changed the title TaskScheduler: include the bucket and the content in the action dedupe key TaskScheduler: include the bucket and the eTag in the action dedupe key Aug 20, 2026
@delthas

delthas commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Moved to 9.6.

@scality scality deleted a comment from bert-e Aug 20, 2026
@bert-e

bert-e commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Waiting for approval

The following approvals are needed before I can proceed with the merge:

  • the author

  • 2 peers

The following reviewers are expecting changes from the author, or must review again:

@delthas
delthas force-pushed the bugfix/BB-810/task-scheduler-dedupe-key branch from 56026f5 to 1db1514 Compare August 20, 2026 15:53
The queue processor pushed the entries of both its consumers into a
single task scheduler: the replication entries of the replication topic,
and the copyLocation actions of the data mover topic. Sharing it makes
tasks of the two kinds serialize on the same queue key and, worse,
deduplicate against each other, although they are distinct work.

Give each consumer its own scheduler, so that a dedupe cache only ever
holds one kind of entry.

Issue: BB-810
The TaskScheduler dedupe key of an ActionQueueEntry omitted the bucket,
so two actions targeting the same object key in different buckets were
considered duplicates, and the second one was silently dropped. Its
third component read target.contentMd5, which no producer has ever set:
the content of a copyLocation action is carried by target.eTag. The key
of the transition of an object in a non-versioned bucket thus
degenerated to `<objectKey>::undefined`, and such an object overwritten
with new contents also collided with its own pending action.

Build the key from the bucket, the version and the eTag, stripped of its
quotes so that the same content always yields the same key.

Issue: BB-810
Dropping a task on a dedupe key match was so far entirely silent, which
leaves no trace to diagnose from when a task is skipped wrongly.

The logger takes the constructor slot of a concurrency parameter that
TaskScheduler never had: that limit is enforced by the consumer, in
BackbeatConsumer._getAvailableSlotsInPipeline().

Issue: BB-810
@delthas
delthas force-pushed the bugfix/BB-810/task-scheduler-dedupe-key branch from 1db1514 to 94795a3 Compare August 20, 2026 15:57
@delthas

delthas commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Moved each consumer to its own scheduler and dropped the prefix. (First commit).

@bert-e

bert-e commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Waiting for approval

The following approvals are needed before I can proceed with the merge:

  • the author

  • 2 peers

@delthas

delthas commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

/approve

@delthas

delthas commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

!done 4h

@bert-e

bert-e commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

In the queue

The changeset has received all authorizations and has been added to the
relevant queue(s). The queue(s) will be merged in the target development
branch(es) as soon as builds have passed.

The changeset will be merged in:

  • ✔️ development/9.6

The following branches will NOT be impacted:

  • development/7.10
  • development/7.4
  • development/7.70
  • development/8.6
  • development/9.0
  • development/9.1
  • development/9.2
  • development/9.3
  • development/9.4
  • development/9.5

This pull request does not target the following hotfix branch(es) so they
will be left untouched:

  • hotfix/7.4.1
  • hotfix/7.4.7
  • hotfix/7.7.0
  • hotfix/7.10.4
  • hotfix/7.10.8
  • hotfix/7.10.12
  • hotfix/7.10.2
  • hotfix/7.4.3
  • hotfix/7.4.9
  • hotfix/7.70.15
  • hotfix/7.4.0
  • hotfix/9.0.4
  • hotfix/7.10.3
  • hotfix/8.2.12
  • hotfix/7.4.4
  • hotfix/7.4.2
  • hotfix/7.8.0
  • hotfix/7.4.10
  • hotfix/7.10.17
  • hotfix/7.4.8
  • hotfix/7.6.0
  • hotfix/7.9.0
  • hotfix/7.2.0
  • hotfix/7.10.0
  • hotfix/9.0.7
  • hotfix/7.70.12
  • hotfix/7.10.1
  • hotfix/7.4.5
  • hotfix/7.4.6
  • hotfix/7.70.1

There is no action required on your side. You will be notified here once
the changeset has been merged. In the unlikely event that the changeset
fails permanently on the queue, a member of the admin team will
contact you to help resolve the matter.

IMPORTANT

Please do not attempt to modify this pull request.

  • Any commit you add on the source branch will trigger a new cycle after the
    current queue is merged.
  • Any commit you add on one of the integration branches will be lost.

If you need this pull request to be removed from the queue, please contact a
member of the admin team now.

The following options are set: approve

@bert-e

bert-e commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

I have successfully merged the changeset of this pull request
into targetted development branches:

  • ✔️ development/9.6

The following branches have NOT changed:

  • development/7.10
  • development/7.4
  • development/7.70
  • development/8.6
  • development/9.0
  • development/9.1
  • development/9.2
  • development/9.3
  • development/9.4
  • development/9.5

Please check the status of the associated issue BB-810.

Goodbye delthas.

@bert-e
bert-e merged commit dc81c3d into development/9.6 Aug 28, 2026
84 of 88 checks passed
@bert-e
bert-e deleted the bugfix/BB-810/task-scheduler-dedupe-key branch August 28, 2026 08:17
@delthas

delthas commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

BB-810: logged 4h; transitioned to Done (Fixed)

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.

4 participants