Skip to main content

replicate_object

Function replicate_object 

Source
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>,
)
where F: Fn(String, String, Bytes, Option<HashMap<String, String>>) -> Fut, Fut: Future<Output = Result<(), String>>,
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: REPLICA so a HEAD on the replica is distinguishable.
  • On callback success, records (source_bucket, source_key) → Completed in the manager iff this task’s generation is 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, records Failed, bumps dropped_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 from ReplicationManager::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 is None and the dispatcher falls back to the source’s logical key (= the AWS-default behaviour). For a versioning-Enabled source the caller passes Some(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.