mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-19 19:16:17 +00:00
9baa92563a
Implements the MinIO active-active read-proxy protocol (P1-5 of the
replication compatibility review): when a GET/HEAD/GetObjectTagging/
PutObjectTagging/DeleteObjectTagging request fails locally with
not-found and the bucket has replication targets, the request is proxied
to the targets in rule order, mirroring bucket-replication.go
proxyGetToReplicationTarget/proxyHeadToRepTarget/proxyTaggingToRepTarget.
Protocol surface:
- Anti-loop: inbound {x-rustfs-,x-minio-}source-proxy-request is parsed
into ObjectOptions (proxy_request + proxy_header_set, matching MinIO
ProxyRequest/ProxyHeaderSet); a request carrying the marker with ANY
value is never re-proxied. Outbound client proxy calls send the marker
as "true"; replication worker convergence HEADs send it as "false" so
a peer's proxy layer cannot answer a convergence check by proxying
back to the source (which would fake Completed without a PUT).
- Target selection: new replication_proxy.rs get_proxy_targets — empty
when the marker is set, versioning is suspended, or no replication
config; otherwise filter_target_arns -> TargetClient lookup, skipping
targets with proxying disabled.
- TargetClient gains head_object_for_proxy/get_object (streaming) and
the three tagging calls. Proxy calls never send the replication-check
SSE-C exemption header; customer SSE-C keys are forwarded verbatim so
the target performs real decryption. Conditional (If-*) headers are
not forwarded (MinIO parity); Range and part_number are, with
parts_count/tag_count/storage_class/expiration passed through.
- Metrics: proxy counters now count only real client proxy traffic,
MinIO-aligned (one total per proxied request, one failed when no
target served it). The previous misattributed counters — replication
worker HEAD/PUT (#2672) and local tagging operations (#2682) — are
removed; ReplProxyMetric now maps the tagging counters instead of
dropping them.
e2e (fake_s3_target extended with tagging + header journaling): proxied
GET body + outbound header contract (marker present, no
replication-check, SSE-C passthrough), HEAD, anti-loop 404 with zero
outbound requests, GetObjectTagging, and metric mapping unit tests.
Rolling note: proxying only activates for buckets with replication
targets; requests carrying the marker keep pre-upgrade behavior.
Refs rustfs/backlog#1675 (P1-5)
77 lines
3.4 KiB
Rust
77 lines
3.4 KiB
Rust
// Copyright 2024 RustFS Team
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
use super::replication_error_boundary::{Error, Result};
|
|
use super::replication_filemeta_boundary::MrfReplicateEntry;
|
|
|
|
/// Kept test-only: the runtime consumer was the worker HEAD's fake proxy
|
|
/// counting (removed in backlog#1675 P1-5); the resyncer tests still pin the
|
|
/// classifier's semantics for the real client read-proxy failure accounting.
|
|
#[cfg(test)]
|
|
pub(crate) use rustfs_replication::should_count_head_proxy_failure;
|
|
pub use rustfs_replication::{BucketReplicationResyncStatus, ResyncOpts, ResyncStatusType, TargetReplicationResyncStatus};
|
|
pub(crate) use rustfs_replication::{
|
|
is_version_id_mismatch, resync_state_accepts_update, sanitize_resync_error_detail, should_auto_resume_resync,
|
|
};
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) const RESYNC_META_FORMAT: u16 = rustfs_replication::resync::RESYNC_META_FORMAT;
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) const RESYNC_META_VERSION: u16 = rustfs_replication::resync::RESYNC_META_VERSION;
|
|
pub(crate) const RESYNC_FILE_MAX_BYTES: usize = rustfs_replication::RESYNC_FILE_MAX_BYTES;
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) const WIRE_ZERO_TIME_UNIX: i64 = rustfs_replication::resync::WIRE_ZERO_TIME_UNIX;
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) const MRF_META_FORMAT: u16 = rustfs_replication::mrf::MRF_META_FORMAT;
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) const MRF_META_VERSION: u16 = rustfs_replication::mrf::MRF_META_VERSION;
|
|
|
|
fn map_replication_error(err: rustfs_replication::Error) -> Error {
|
|
match err {
|
|
rustfs_replication::Error::CorruptedFormat => Error::CorruptedFormat,
|
|
rustfs_replication::Error::Other(err) => Error::other(err),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn encode_resync_file(status: &BucketReplicationResyncStatus) -> Result<Vec<u8>> {
|
|
rustfs_replication::encode_resync_file(status).map_err(map_replication_error)
|
|
}
|
|
|
|
pub(crate) fn decode_resync_file(data: &[u8]) -> Result<BucketReplicationResyncStatus> {
|
|
rustfs_replication::decode_resync_file(data).map_err(map_replication_error)
|
|
}
|
|
|
|
pub(crate) fn encode_mrf_file(entries: &[MrfReplicateEntry]) -> Result<Vec<u8>> {
|
|
rustfs_replication::encode_mrf_file(entries).map_err(map_replication_error)
|
|
}
|
|
|
|
pub(crate) fn decode_mrf_file(data: &[u8]) -> Result<Vec<MrfReplicateEntry>> {
|
|
rustfs_replication::decode_mrf_file(data).map_err(map_replication_error)
|
|
}
|