pub async fn replicate_object<F, Fut>(
rule: ReplicationRule,
source_bucket: String,
source_key: String,
body: Bytes,
metadata: Option<HashMap<String, String>>,
do_put: F,
manager: Arc<ReplicationManager>,
generation: u64,
destination_key_override: Option<String>,
source_lock_state: Option<ObjectLockState>,
)Expand description
Replicate one source-bucket object to the rule’s destination bucket.
The caller supplies a do_put callback that performs the actual
destination-bucket PUT (so unit tests can drive the dispatcher
without needing a full backend). The callback receives:
(destination_bucket, key, body, metadata) and returns a
Result<(), String> whose Err triggers the retry / failure path.
Behaviour:
- Stamps the destination metadata with
x-amz-replication-status: REPLICAso a HEAD on the replica is distinguishable. - On callback success, records
(source_bucket, source_key) → Completedin the manager iff this task’sgenerationis not already overtaken (CAS-style guard — see [ReplicationManager:: record_status_if_newer]). - On callback failure, retries up to [
RETRY_ATTEMPTS] times with exponential backoff (50ms / 100ms / 200ms). After the budget is exhausted, recordsFailed, bumpsdropped_total, and emits the matching Prometheus counter — also CAS-guarded.
§v0.8.2 #61 — generation token + destination key override
The two new parameters fix the audit’s C-1 + C-3 findings:
generation— monotonic per-source-PUT token fromReplicationManager::next_generation. CAS-stamps the source’s status + suppresses the actual destination PUT when the token has been overtaken. Without this guard, a slow retry of PUT-A could land in the destination after PUT-B has already replicated — rolling the destination back to A’s bytes. With the guard, A’s task notices B’s higher generation has won and silently drops its destination write.destination_key_override— the storage-side key the destination bucket should write under. For an unversioned source this isNoneand the dispatcher falls back to the source’s logical key (= the AWS-default behaviour). For a versioning-Enabled source the caller passesSome(versioned_shadow_key(key, vid))so the destination’s version chain receives the new version under the same shadow path the source uses (= a?versionId=GET on the destination resolves through the same shadow-key lookup as the source).
§v0.8.3 #68 — Object Lock state propagation (audit M-1)
source_lock_state carries the source object’s WORM posture
(mode + retain_until + legal_hold_on) at PUT time. When Some,
the destination PUT is decorated with the AWS-wire lock headers
(x-amz-object-lock-mode, x-amz-object-lock-retain-until-date,
x-amz-object-lock-legal-hold) on the metadata map so the
destination side’s put_object (or its caller) can persist the
same lock state on the replica. Without this, a Compliance /
Governance / legal-hold protected source had a destination
replica that the destination operator could freely DELETE — the
“WORM compliance posture survives DR” guarantee leaked.
None (no lock state on the source) keeps the legacy behaviour:
no extra headers, replica is freely deletable on the destination.