mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-27 15:37:02 +00:00
fix(replication): mark version-id fallback ETag match as Completed, not Failed (backlog#860) (#4310)
During resync against an AWS-style target that rejects RustFS UUID versionIds,
the code retries HEAD without a versionId and compares ETags. On a match it set
`replication_action = None` ("already in sync, nothing to copy") but did not
return, so control fell through to `if replication_action != ReplicationAction::All`
— a branch meant only for the unsupported metadata-only case — and stamped the
object FAILED with "metadata-only replication is not implemented". The target
already held an identical object, yet the source recorded FAILED forever, so
AWS-style targets never converged and the MRF kept re-queuing.
Handle `ReplicationAction::None` explicitly before that branch: record it as
Completed (with the resync timestamp/`replication_resynced` bookkeeping for
ExistingObject + reset_id, mirroring the HEAD-success None path) and return.
Only `ReplicationAction::Metadata` now takes the metadata-unsupported failure
branch; `All` still proceeds to the copy. This path is the only way `None`
reaches that point (the HEAD-success None case already returns earlier).
Refs backlog#799 (B11).
This commit is contained in:
@@ -2658,6 +2658,28 @@ impl ReplicateObjectInfoExt for ReplicateObjectInfo {
|
|||||||
rinfo.size = size;
|
rinfo.size = size;
|
||||||
rinfo.replication_action = replication_action;
|
rinfo.replication_action = replication_action;
|
||||||
|
|
||||||
|
if replication_action == ReplicationAction::None {
|
||||||
|
// The target already holds a matching object (reached here only via
|
||||||
|
// the version-id fallback ETag match above) — there is nothing to
|
||||||
|
// copy. Record it as synced and return, instead of falling into the
|
||||||
|
// metadata-unsupported failure branch below, which previously left
|
||||||
|
// AWS-style targets permanently FAILED and never converging
|
||||||
|
// (backlog#860 / #799 B11).
|
||||||
|
if self.op_type == ReplicationType::ExistingObject && !tgt_client.reset_id.is_empty() {
|
||||||
|
rinfo.resync_timestamp = format!(
|
||||||
|
"{};{}",
|
||||||
|
OffsetDateTime::now_utc()
|
||||||
|
.format(&Rfc3339)
|
||||||
|
.unwrap_or_else(|_| "invalid-time".to_string()),
|
||||||
|
tgt_client.reset_id
|
||||||
|
);
|
||||||
|
rinfo.replication_resynced = true;
|
||||||
|
}
|
||||||
|
rinfo.duration = (OffsetDateTime::now_utc() - start_time).unsigned_abs();
|
||||||
|
return rinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// action == Metadata: metadata-only replication is not implemented.
|
||||||
if replication_action != ReplicationAction::All {
|
if replication_action != ReplicationAction::All {
|
||||||
rinfo.replication_status = ReplicationStatusType::Failed;
|
rinfo.replication_status = ReplicationStatusType::Failed;
|
||||||
rinfo.error = Some(ERR_REPLICATION_METADATA_COPY_UNSUPPORTED.to_string());
|
rinfo.error = Some(ERR_REPLICATION_METADATA_COPY_UNSUPPORTED.to_string());
|
||||||
|
|||||||
Reference in New Issue
Block a user