mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-27 15:37:02 +00:00
refactor: clean config storage boundaries (#3489)
This commit is contained in:
@@ -44,7 +44,7 @@ use crate::client::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
disk::DiskAPI,
|
disk::DiskAPI,
|
||||||
store_api::{GetObjectReader, ObjectInfo, StorageAPI},
|
store_api::{GetObjectReader, ObjectInfo},
|
||||||
};
|
};
|
||||||
use rustfs_utils::hash::EMPTY_STRING_SHA256_HASH;
|
use rustfs_utils::hash::EMPTY_STRING_SHA256_HASH;
|
||||||
|
|
||||||
|
|||||||
@@ -1217,12 +1217,7 @@ mod tests {
|
|||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::global::{is_dist_erasure, is_erasure, is_erasure_sd, update_erasure_type};
|
use crate::global::{is_dist_erasure, is_erasure, is_erasure_sd, update_erasure_type};
|
||||||
use crate::set_disk::SetDisks;
|
use crate::set_disk::SetDisks;
|
||||||
use crate::store_api::{
|
use crate::store_api::{GetObjectReader, HTTPRangeSpec, NamespaceLocking, ObjectIO, ObjectInfo, ObjectOptions, PutObjReader};
|
||||||
BucketInfo, BucketOperations, BucketOptions, CompletePart, DeleteBucketOptions, DeletedObject, GetObjectReader,
|
|
||||||
HTTPRangeSpec, HealOperations, ListMultipartsInfo, ListObjectVersionsInfo, ListObjectsV2Info, ListOperations,
|
|
||||||
MakeBucketOptions, MultipartInfo, MultipartOperations, MultipartUploadResult, NamespaceLocking, ObjectIO, ObjectInfo,
|
|
||||||
ObjectOperations, ObjectOptions, ObjectToDelete, PartInfo, PutObjReader, StorageAPI, WalkOptions,
|
|
||||||
};
|
|
||||||
use http::HeaderMap;
|
use http::HeaderMap;
|
||||||
use rustfs_config::audit::{AUDIT_AMQP_SUB_SYS, AUDIT_KAFKA_SUB_SYS, AUDIT_MQTT_SUB_SYS, AUDIT_WEBHOOK_SUB_SYS};
|
use rustfs_config::audit::{AUDIT_AMQP_SUB_SYS, AUDIT_KAFKA_SUB_SYS, AUDIT_MQTT_SUB_SYS, AUDIT_WEBHOOK_SUB_SYS};
|
||||||
use rustfs_config::notify::{
|
use rustfs_config::notify::{
|
||||||
@@ -1233,7 +1228,6 @@ mod tests {
|
|||||||
use rustfs_config::{
|
use rustfs_config::{
|
||||||
DEFAULT_DELIMITER, ENABLE_KEY, EnableState, MYSQL_DSN_STRING, MYSQL_MAX_OPEN_CONNECTIONS, MYSQL_QUEUE_DIR, MYSQL_TABLE,
|
DEFAULT_DELIMITER, ENABLE_KEY, EnableState, MYSQL_DSN_STRING, MYSQL_MAX_OPEN_CONNECTIONS, MYSQL_QUEUE_DIR, MYSQL_TABLE,
|
||||||
};
|
};
|
||||||
use rustfs_filemeta::FileInfo;
|
|
||||||
use rustfs_lock::client::LockClient;
|
use rustfs_lock::client::LockClient;
|
||||||
use rustfs_lock::client::local::LocalClient;
|
use rustfs_lock::client::local::LocalClient;
|
||||||
use rustfs_lock::{LockError, LockInfo, LockResponse, LockStats};
|
use rustfs_lock::{LockError, LockInfo, LockResponse, LockStats};
|
||||||
@@ -1249,7 +1243,6 @@ mod tests {
|
|||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::io::{AsyncRead, ReadBuf};
|
use tokio::io::{AsyncRead, ReadBuf};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use tokio_util::sync::CancellationToken;
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct FailingClient;
|
struct FailingClient;
|
||||||
@@ -1457,277 +1450,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl BucketOperations for LockingConfigStorage {
|
|
||||||
async fn make_bucket(&self, _bucket: &str, _opts: &MakeBucketOptions) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_bucket_info(&self, _bucket: &str, _opts: &BucketOptions) -> Result<BucketInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn list_bucket(&self, _opts: &BucketOptions) -> Result<Vec<BucketInfo>> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_bucket(&self, _bucket: &str, _opts: &DeleteBucketOptions) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl ObjectOperations for LockingConfigStorage {
|
|
||||||
async fn get_object_info(&self, _bucket: &str, _object: &str, _opts: &ObjectOptions) -> Result<ObjectInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn verify_object_integrity(&self, _bucket: &str, _object: &str, _opts: &ObjectOptions) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn copy_object(
|
|
||||||
&self,
|
|
||||||
_src_bucket: &str,
|
|
||||||
_src_object: &str,
|
|
||||||
_dst_bucket: &str,
|
|
||||||
_dst_object: &str,
|
|
||||||
_src_info: &mut ObjectInfo,
|
|
||||||
_src_opts: &ObjectOptions,
|
|
||||||
_dst_opts: &ObjectOptions,
|
|
||||||
) -> Result<ObjectInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_object_version(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_fi: &FileInfo,
|
|
||||||
_force_del_marker: bool,
|
|
||||||
) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_object(&self, _bucket: &str, _object: &str, _opts: ObjectOptions) -> Result<ObjectInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_objects(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_objects: Vec<ObjectToDelete>,
|
|
||||||
_opts: ObjectOptions,
|
|
||||||
) -> (Vec<DeletedObject>, Vec<Option<Error>>) {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn put_object_metadata(&self, _bucket: &str, _object: &str, _opts: &ObjectOptions) -> Result<ObjectInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_object_tags(&self, _bucket: &str, _object: &str, _opts: &ObjectOptions) -> Result<String> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn put_object_tags(&self, _bucket: &str, _object: &str, _tags: &str, _opts: &ObjectOptions) -> Result<ObjectInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete_object_tags(&self, _bucket: &str, _object: &str, _opts: &ObjectOptions) -> Result<ObjectInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn add_partial(&self, _bucket: &str, _object: &str, _version_id: &str) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn transition_object(&self, _bucket: &str, _object: &str, _opts: &ObjectOptions) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn restore_transitioned_object(self: Arc<Self>, _bucket: &str, _object: &str, _opts: &ObjectOptions) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl ListOperations for LockingConfigStorage {
|
|
||||||
async fn list_objects_v2(
|
|
||||||
self: Arc<Self>,
|
|
||||||
_bucket: &str,
|
|
||||||
_prefix: &str,
|
|
||||||
_continuation_token: Option<String>,
|
|
||||||
_delimiter: Option<String>,
|
|
||||||
_max_keys: i32,
|
|
||||||
_fetch_owner: bool,
|
|
||||||
_start_after: Option<String>,
|
|
||||||
_incl_deleted: bool,
|
|
||||||
) -> Result<ListObjectsV2Info> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn list_object_versions(
|
|
||||||
self: Arc<Self>,
|
|
||||||
_bucket: &str,
|
|
||||||
_prefix: &str,
|
|
||||||
_marker: Option<String>,
|
|
||||||
_version_marker: Option<String>,
|
|
||||||
_delimiter: Option<String>,
|
|
||||||
_max_keys: i32,
|
|
||||||
) -> Result<ListObjectVersionsInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn walk(
|
|
||||||
self: Arc<Self>,
|
|
||||||
_rx: CancellationToken,
|
|
||||||
_bucket: &str,
|
|
||||||
_prefix: &str,
|
|
||||||
_result: tokio::sync::mpsc::Sender<crate::store_api::ObjectInfoOrErr>,
|
|
||||||
_opts: WalkOptions,
|
|
||||||
) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl MultipartOperations for LockingConfigStorage {
|
|
||||||
async fn list_multipart_uploads(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_prefix: &str,
|
|
||||||
_key_marker: Option<String>,
|
|
||||||
_upload_id_marker: Option<String>,
|
|
||||||
_delimiter: Option<String>,
|
|
||||||
_max_uploads: usize,
|
|
||||||
) -> Result<ListMultipartsInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn new_multipart_upload(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_opts: &ObjectOptions,
|
|
||||||
) -> Result<MultipartUploadResult> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn copy_object_part(
|
|
||||||
&self,
|
|
||||||
_src_bucket: &str,
|
|
||||||
_src_object: &str,
|
|
||||||
_dst_bucket: &str,
|
|
||||||
_dst_object: &str,
|
|
||||||
_upload_id: &str,
|
|
||||||
_part_id: usize,
|
|
||||||
_start_offset: i64,
|
|
||||||
_length: i64,
|
|
||||||
_src_info: &ObjectInfo,
|
|
||||||
_src_opts: &ObjectOptions,
|
|
||||||
_dst_opts: &ObjectOptions,
|
|
||||||
) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn put_object_part(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_upload_id: &str,
|
|
||||||
_part_id: usize,
|
|
||||||
_data: &mut PutObjReader,
|
|
||||||
_opts: &ObjectOptions,
|
|
||||||
) -> Result<PartInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_multipart_info(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_upload_id: &str,
|
|
||||||
_opts: &ObjectOptions,
|
|
||||||
) -> Result<MultipartInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn list_object_parts(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_upload_id: &str,
|
|
||||||
_part_number_marker: Option<usize>,
|
|
||||||
_max_parts: usize,
|
|
||||||
_opts: &ObjectOptions,
|
|
||||||
) -> Result<crate::store_api::ListPartsInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn abort_multipart_upload(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_upload_id: &str,
|
|
||||||
_opts: &ObjectOptions,
|
|
||||||
) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn complete_multipart_upload(
|
|
||||||
self: Arc<Self>,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_upload_id: &str,
|
|
||||||
_uploaded_parts: Vec<CompletePart>,
|
|
||||||
_opts: &ObjectOptions,
|
|
||||||
) -> Result<ObjectInfo> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl HealOperations for LockingConfigStorage {
|
|
||||||
async fn heal_format(&self, _dry_run: bool) -> Result<(rustfs_madmin::heal_commands::HealResultItem, Option<Error>)> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn heal_bucket(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_opts: &rustfs_common::heal_channel::HealOpts,
|
|
||||||
) -> Result<rustfs_madmin::heal_commands::HealResultItem> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn heal_object(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_version_id: &str,
|
|
||||||
_opts: &rustfs_common::heal_channel::HealOpts,
|
|
||||||
) -> Result<(rustfs_madmin::heal_commands::HealResultItem, Option<Error>)> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_pool_and_set(&self, _id: &str) -> Result<(Option<usize>, Option<usize>, Option<usize>)> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn check_abandoned_parts(
|
|
||||||
&self,
|
|
||||||
_bucket: &str,
|
|
||||||
_object: &str,
|
|
||||||
_opts: &rustfs_common::heal_channel::HealOpts,
|
|
||||||
) -> Result<()> {
|
|
||||||
panic!("unused in test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl StorageAPI for LockingConfigStorage {}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl NamespaceLocking for LockingConfigStorage {
|
impl NamespaceLocking for LockingConfigStorage {
|
||||||
async fn new_ns_lock(&self, bucket: &str, object: &str) -> Result<rustfs_lock::NamespaceLockWrapper> {
|
async fn new_ns_lock(&self, bucket: &str, object: &str) -> Result<rustfs_lock::NamespaceLockWrapper> {
|
||||||
|
|||||||
@@ -1552,8 +1552,8 @@ fn get_quorum_disk_infos(disks: &[DiskStore], infos: &[DiskInfo], read_quorum: u
|
|||||||
for (i, info) in infos.iter().enumerate() {
|
for (i, info) in infos.iter().enumerate() {
|
||||||
let mutations = info.metrics.total_deletes + info.metrics.total_writes;
|
let mutations = info.metrics.total_deletes + info.metrics.total_writes;
|
||||||
if mutations >= common_mutations {
|
if mutations >= common_mutations {
|
||||||
new_disks.push(disks[i].clone()); // Assuming StorageAPI derives Clone
|
new_disks.push(disks[i].clone());
|
||||||
new_infos.push(infos[i].clone()); // Assuming DiskInfo derives Clone
|
new_infos.push(infos[i].clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ behind narrower contracts.
|
|||||||
| `DEFAULT_KVS` | `crates/ecstore/src/config/mod.rs` | Registry for defaults across storage class, scanner, notify, audit, and OIDC. | Move defaults only after an explicit registration contract exists. |
|
| `DEFAULT_KVS` | `crates/ecstore/src/config/mod.rs` | Registry for defaults across storage class, scanner, notify, audit, and OIDC. | Move defaults only after an explicit registration contract exists. |
|
||||||
| `GLOBAL_SERVER_CONFIG` | `crates/ecstore/src/config/mod.rs` | Process-wide mutable server config snapshot. | Migrate readers behind `AppContext` or a server-config provider before changing storage. |
|
| `GLOBAL_SERVER_CONFIG` | `crates/ecstore/src/config/mod.rs` | Process-wide mutable server config snapshot. | Migrate readers behind `AppContext` or a server-config provider before changing storage. |
|
||||||
| `ConfigSys::init` | `crates/ecstore/src/config/mod.rs` | Reads persisted config, looks up derived config, and stores the global snapshot. | Startup order must remain unchanged until the lifecycle contract owns this dependency. |
|
| `ConfigSys::init` | `crates/ecstore/src/config/mod.rs` | Reads persisted config, looks up derived config, and stores the global snapshot. | Startup order must remain unchanged until the lifecycle contract owns this dependency. |
|
||||||
| `read_config_without_migrate` | `crates/ecstore/src/config/com.rs` | Loads persisted server config through `StorageAPI`. | Persistence stays in `ecstore` until pure model and persistence are separated. |
|
| `read_config_without_migrate` | `crates/ecstore/src/config/com.rs` | Loads persisted server config through ECStore-owned object I/O and storage-admin contracts. | Persistence stays in `ecstore` until pure model and persistence are separated. |
|
||||||
| `save_server_config` | `crates/ecstore/src/config/com.rs` | Persists the canonical server config object. | Preserve external object shape and config-history behavior. |
|
| `save_server_config` | `crates/ecstore/src/config/com.rs` | Persists the canonical server config object. | Preserve external object shape and config-history behavior. |
|
||||||
| `get_global_server_config` / `set_global_server_config` | `crates/ecstore/src/config/mod.rs` | Clone/read and replace the global server-config snapshot. | Do not remove until all runtime readers have an injected provider path. |
|
| `get_global_server_config` / `set_global_server_config` | `crates/ecstore/src/config/mod.rs` | Clone/read and replace the global server-config snapshot. | Do not remove until all runtime readers have an injected provider path. |
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ behind narrower contracts.
|
|||||||
| Files | Current usage |
|
| Files | Current usage |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `crates/ecstore/src/config/mod.rs` | Defines `KV`, `KVS`, `Config`, defaults, global snapshot, initialization, and tests. |
|
| `crates/ecstore/src/config/mod.rs` | Defines `KV`, `KVS`, `Config`, defaults, global snapshot, initialization, and tests. |
|
||||||
| `crates/ecstore/src/config/com.rs` | Encodes, decodes, reads, writes, creates, and normalizes server config objects through `StorageAPI`. |
|
| `crates/ecstore/src/config/com.rs` | Encodes, decodes, reads, writes, creates, and normalizes server config objects through ECStore-local persistence helpers. |
|
||||||
| `crates/ecstore/src/config/{notify,audit,oidc,scanner,storageclass}.rs` | Register default `KVS` values and subsystem-specific parsing helpers. |
|
| `crates/ecstore/src/config/{notify,audit,oidc,scanner,storageclass}.rs` | Register default `KVS` values and subsystem-specific parsing helpers. |
|
||||||
| `crates/ecstore/src/store.rs` | Exposes store-level server-config accessors that delegate to the global config snapshot. |
|
| `crates/ecstore/src/store.rs` | Exposes store-level server-config accessors that delegate to the global config snapshot. |
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ behind narrower contracts.
|
|||||||
| `KVS` is the effective target config carrier | Notify, audit, and target factories consume `KVS` after file/env merge. | Keep `KVS` API stable until target descriptor and runtime crates are behind a shared contract. |
|
| `KVS` is the effective target config carrier | Notify, audit, and target factories consume `KVS` after file/env merge. | Keep `KVS` API stable until target descriptor and runtime crates are behind a shared contract. |
|
||||||
| `DEFAULT_KVS` registration is global | Defaults are initialized centrally and used by admin validation/rendering. | Add a registration contract before changing initialization order. |
|
| `DEFAULT_KVS` registration is global | Defaults are initialized centrally and used by admin validation/rendering. | Add a registration contract before changing initialization order. |
|
||||||
| Global snapshot readers still exist | Server, admin, IAM, scanner, and site-replication paths can still read global config. | Migrate readers through `AppContext`/provider paths in small steps after the model contract is stable. |
|
| Global snapshot readers still exist | Server, admin, IAM, scanner, and site-replication paths can still read global config. | Migrate readers through `AppContext`/provider paths in small steps after the model contract is stable. |
|
||||||
| Persistence helpers depend on `StorageAPI` | Moving them with the pure model would pull storage implementation dependencies upward. | Keep read/write helpers in `ecstore` until a storage-facing persistence contract is explicit. |
|
| Persistence helpers depend on ECStore storage contracts | Moving them with the pure model would pull storage implementation dependencies upward. | Keep read/write helpers in `ecstore` until a storage-facing persistence contract is explicit. |
|
||||||
|
|
||||||
## Recommended Migration Order
|
## Recommended Migration Order
|
||||||
|
|
||||||
@@ -176,8 +176,8 @@ behind narrower contracts.
|
|||||||
behavior, and representative admin config rendering paths.
|
behavior, and representative admin config rendering paths.
|
||||||
5. Migrate global `Config` readers behind `ServerConfigInterface` or a narrower
|
5. Migrate global `Config` readers behind `ServerConfigInterface` or a narrower
|
||||||
provider in small PRs.
|
provider in small PRs.
|
||||||
6. Move persistence helpers only after `StorageAPI` dependencies can stay below
|
6. Move persistence helpers only after object-I/O and storage-admin dependencies
|
||||||
the model contract.
|
can stay below the model contract.
|
||||||
7. Evaluate crate split only after consumers no longer need old paths except
|
7. Evaluate crate split only after consumers no longer need old paths except
|
||||||
explicit `RUSTFS_COMPAT_TODO(<task-id>)` compatibility shims.
|
explicit `RUSTFS_COMPAT_TODO(<task-id>)` compatibility shims.
|
||||||
|
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
## Current Context
|
## Current Context
|
||||||
|
|
||||||
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
|
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
|
||||||
- Branch: `overtrue/arch-storage-namespace-lock-large-cleanup`
|
- Branch: `overtrue/arch-config-storage-boundary-cleanup`
|
||||||
- Baseline: `origin/main` at `49c0f131205035d125271bb5b87db5b0f5bc2a6d`
|
- Baseline: `origin/main` at `fbab160c2b09075f5e2503a669d82917ef82d40e`
|
||||||
- PR type for this branch: `consumer-migration`
|
- PR type for this branch: `consumer-migration`
|
||||||
- Runtime behavior changes: no external behavior change expected.
|
- Runtime behavior changes: no external behavior change expected.
|
||||||
- Rust code changes: narrow replication pool, resync, delete replication, and
|
- Rust code changes: remove stale full `StorageAPI` coupling from config
|
||||||
object replication storage bounds away from full `StorageAPI` to their actual
|
persistence tests, an unused S3 remove-client import, and an obsolete storage
|
||||||
object I/O, object operation, list, and namespace-lock capabilities.
|
list comment.
|
||||||
- CI/script changes: none.
|
- CI/script changes: none.
|
||||||
- Docs changes: record the current `API-012` consumer cleanup slice and its
|
- Docs changes: refresh the ECStore config persistence inventory and current
|
||||||
verification state.
|
verification state.
|
||||||
|
|
||||||
## Phase 0 Tasks
|
## Phase 0 Tasks
|
||||||
@@ -419,6 +419,9 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
full `StorageAPI` when the helper only needs `ObjectIO`,
|
full `StorageAPI` when the helper only needs `ObjectIO`,
|
||||||
`ObjectOperations`, `BucketOperations`, `ListOperations`, or
|
`ObjectOperations`, `BucketOperations`, `ListOperations`, or
|
||||||
`StorageAdminApi`.
|
`StorageAdminApi`.
|
||||||
|
- Cleanup slice: remove stale full `StorageAPI` dependencies from config
|
||||||
|
persistence test support after the server-config persistence helpers moved
|
||||||
|
to their actual object I/O and storage-admin bounds.
|
||||||
- Acceptance: metadata helper contracts express the actual operation group
|
- Acceptance: metadata helper contracts express the actual operation group
|
||||||
they need, while callers and persistence behavior remain unchanged.
|
they need, while callers and persistence behavior remain unchanged.
|
||||||
|
|
||||||
@@ -463,10 +466,10 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
catalog backend and rebalance metadata helper consumers away from full
|
catalog backend and rebalance metadata helper consumers away from full
|
||||||
`StorageAPI` where they only need object I/O, object operations, list
|
`StorageAPI` where they only need object I/O, object operations, list
|
||||||
operations, and namespace locking.
|
operations, and namespace locking.
|
||||||
- Current cleanup slice: narrow replication pool, resync leader-lock, delete
|
- Completed follow-up slice: `rustfs/rustfs#3485` narrowed replication pool,
|
||||||
replication, object replication, and multipart replication helpers away
|
resync leader-lock, delete replication, object replication, and multipart
|
||||||
from full `StorageAPI` where they only need object I/O, object operations,
|
replication helpers away from full `StorageAPI` where they only need object
|
||||||
list operations, and namespace locking.
|
I/O, object operations, list operations, and namespace locking.
|
||||||
- Acceptance: table catalog object backend contracts express the actual
|
- Acceptance: table catalog object backend contracts express the actual
|
||||||
object read/write, metadata/delete, list, and namespace-lock capabilities
|
object read/write, metadata/delete, list, and namespace-lock capabilities
|
||||||
they need; namespace-lock consumers depend on `NamespaceLocking` instead of
|
they need; namespace-lock consumers depend on `NamespaceLocking` instead of
|
||||||
@@ -759,18 +762,16 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
|
|
||||||
| Expert | Status | Notes |
|
| Expert | Status | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Quality/architecture | passed | Replication consumers now depend on a local replication storage capability boundary plus object-I/O-only helper bounds, without changing replication method bodies. |
|
| Quality/architecture | passed | Config persistence tests now express their actual object I/O, namespace-lock, and storage-admin requirements instead of a full storage facade. |
|
||||||
| Migration preservation | passed | Resync leader locks, per-object replication locks, delete replication, object reader flow, multipart upload flow, MRF recovery, and replication scheduling semantics are unchanged. |
|
| Migration preservation | passed | Config object encoding/decoding, metadata reads, namespace-lock behavior, and S3 remove-client behavior are unchanged. |
|
||||||
| Testing/verification | passed | Focused replication tests, storage API compatibility test, compile checks, migration/layer guards, formatting, diff hygiene, Rust risk scan, and full `make pre-commit` passed. |
|
| Testing/verification | passed | Focused config tests, compile checks, migration/layer guards, formatting, diff hygiene, Rust risk scan, and full `make pre-commit` passed. |
|
||||||
|
|
||||||
## Verification Notes
|
## Verification Notes
|
||||||
|
|
||||||
Passed on `49c0f131205035d125271bb5b87db5b0f5bc2a6d`:
|
Passed on `fbab160c2b09075f5e2503a669d82917ef82d40e`:
|
||||||
|
|
||||||
- `cargo check -p rustfs-ecstore`: passed.
|
- `cargo check -p rustfs-ecstore`: passed.
|
||||||
- `cargo test -p rustfs-ecstore bucket::replication --no-fail-fast`: passed.
|
- `cargo test -p rustfs-ecstore config::com --no-fail-fast`: passed.
|
||||||
- `cargo test -p rustfs-ecstore --test storage_api_compat_test --no-fail-fast`:
|
|
||||||
passed.
|
|
||||||
- `cargo check -p rustfs -p rustfs-ecstore`: passed.
|
- `cargo check -p rustfs -p rustfs-ecstore`: passed.
|
||||||
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
||||||
- `./scripts/check_layer_dependencies.sh`: passed.
|
- `./scripts/check_layer_dependencies.sh`: passed.
|
||||||
@@ -783,17 +784,16 @@ Passed on `49c0f131205035d125271bb5b87db5b0f5bc2a6d`:
|
|||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- This slice keeps the existing replication method bodies unchanged while
|
- This slice removes test-only full facade scaffolding after config persistence
|
||||||
narrowing the generic storage capabilities they require.
|
helpers already moved to narrower object I/O and storage-admin contracts.
|
||||||
- Replication storage still depends on object I/O, object metadata/delete
|
- The S3 remove client had a stale full facade import only; behavior remains
|
||||||
operations, bucket walking, and namespace locking; multipart replication
|
unchanged.
|
||||||
helpers only need object reader access to stream source ranges.
|
|
||||||
- The slice does not remove the full storage facade or move traits across crate
|
- The slice does not remove the full storage facade or move traits across crate
|
||||||
boundaries.
|
boundaries.
|
||||||
|
|
||||||
## Handoff Notes
|
## Handoff Notes
|
||||||
|
|
||||||
- API-012 replication storage cleanup is locally verified and current with
|
- Config storage boundary cleanup is locally verified and current with
|
||||||
`origin/main`.
|
`origin/main`.
|
||||||
- Remaining namespace-lock cleanup can continue by migrating other consumers
|
- Remaining storage-facade cleanup can continue by migrating other consumers
|
||||||
that no longer need the full storage facade.
|
that no longer need the full storage facade.
|
||||||
|
|||||||
Reference in New Issue
Block a user