diff --git a/docs/architecture/migration-progress.md b/docs/architecture/migration-progress.md index aa5e00233..843e95a4a 100644 --- a/docs/architecture/migration-progress.md +++ b/docs/architecture/migration-progress.md @@ -5,16 +5,16 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block ## Current Context - Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660) -- Branch: `overtrue/arch-config-reload-preservation` -- Baseline: `origin/main` at `6b1e114b39a51166a872388ad64f86ee3d910864` -- PR type for this branch: `test-only` -- Runtime behavior changes: none; config reload and shutdown behavior are - preserved while their no-worker-mutation and shutdown-order assumptions are - made testable. -- Rust code changes: add module-local config reload and background shutdown - plans plus focused tests for `TEST-BGC-002`. +- Branch: `overtrue/arch-app-context-split` +- Baseline: `origin/main` at `af291afb930e072d162ff10c63e33c091b706e58` +- PR type for this branch: `pure-move` +- Runtime behavior changes: none; `crate::app::context::*` remains the public + import path and resolver/global fallback semantics are unchanged. +- Rust code changes: split `rustfs/src/app/context.rs` into module-local + `interfaces`, `handles`, `global`, and `compat` files behind the existing + `app::context` module. - CI/script changes: none. -- Docs changes: record `TEST-BGC-002` config reload preservation coverage. +- Docs changes: record `CTX-001` AppContext file split scope. ## Phase 0 Tasks @@ -132,6 +132,29 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block initialization; global server-config reads and writes keep the same `std::sync::RwLock>` clone semantics. +## Phase 1b Context Foundation Tasks + +- [x] `CTX-001` Split AppContext files. + - Current branch: split `rustfs/src/app/context.rs` into `interfaces`, + `handles`, `global`, and `compat` submodules. + - Acceptance: old `crate::app::context::*` imports continue to compile via + re-exports; context-first and global fallback resolver bodies are moved + without semantic changes. + - Must preserve: AppContext construction, default adapters, global singleton + initialization, resolver fallback order, and all consumer import paths. + - Verification: formatting, compile checks, migration guards, diff hygiene, + Rust risk scan, and full `make pre-commit`. +- [ ] `CTX-002` Add resolver compatibility tests. + - Do: test context-first and global fallback for KMS runtime, bucket + metadata, object store, endpoints, tier config, server config, and buffer + config. + - Acceptance: context wins when present and global fallback works when absent. +- [ ] `CTX-003` Add IAM deferred recovery readiness test. + - Do: verify IAM degraded recovery can still publish `IamReady` and + `FullReady`. + - Acceptance: boot/lifecycle changes cannot lose deferred readiness + publication. + ## Phase 1 Security Governance Tasks - [x] `S-001` Add `crates/security-governance`. @@ -437,45 +460,40 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block ## Next PRs -1. `behavior-change`: add another low-risk read-only status surface now that - config-reload and shutdown assumptions have dedicated preservation tests. -2. `test-only`: extend preservation coverage only if the next controller touches - additional startup/shutdown or config reload assumptions. +1. `test-only`: add CTX-002 resolver compatibility tests before migrating more + consumers to AppContext-first access. +2. `test-only`: add CTX-003 IAM deferred recovery readiness coverage before + boot phase extraction. ## Pre-Push Review Log | Expert | Status | Notes | |---|---|---| -| Quality/architecture | pass | Confirmed the new plans are module-local test seams only and do not add a generic scheduler, registry, route, or public API. | -| Migration preservation | pass | Confirmed reload plans report `worker_mutation: none`, bucket lifecycle/replication remain outside dynamic server-config reload, and shutdown keeps scanner before AHM. | -| Testing/verification | pass | Focused tests, formatting, diff hygiene, migration guards, Rust risk scan, and `make pre-commit` passed. | +| Quality/architecture | pass | Pure module split behind the existing `app::context` root; no service container, public API, or runtime behavior added. | +| Migration preservation | pass | Re-exports preserve `crate::app::context::*`; AppContext construction, default handles, singleton initialization, and resolver fallback order are unchanged. | +| Testing/verification | pass | Focused compile, formatting, diff hygiene, migration guards, Rust risk scan, and full `make pre-commit` passed. | ## Verification Notes -Passed on `6b1e114b39a51166a872388ad64f86ee3d910864`: -- `cargo test -p rustfs --bin rustfs background_shutdown_plan_keeps_scanner_before_ahm`; 1 passed. -- `cargo test -p rustfs background_config_reload_plan_never_mutates_workers`; 1 passed. +Passed on `af291afb930e072d162ff10c63e33c091b706e58`: - `cargo fmt --all`. - `cargo fmt --all --check`. +- `cargo check -p rustfs --lib`. +- `cargo check -p rustfs --bin rustfs`. - `git diff --check`. - `./scripts/check_architecture_migration_rules.sh`. - `./scripts/check_layer_dependencies.sh`. -- Rust risk scan for changed Rust files; only pre-existing test `expect`, - startup `expect`, import alias `as`, and startup `eprintln!` matches remain; - added-line risky-pattern scan found no matches. -- `make pre-commit`; all checks passed, including nextest 5882 passed and 111 +- Rust risk scan for changed Rust files; no matches. +- `make pre-commit`; all checks passed, including nextest 5883 passed and 111 skipped. Notes: -- This slice does not make dynamic config reload start, stop, restart, resize, - or wake scanner/heal/lifecycle/replication workers. -- The shutdown plan preserves the existing scanner before AHM order and keeps - scanner shutdown implying AHM shutdown. +- This slice moves code between files only; it keeps `crate::app::context::*` + imports working through the module root. +- Resolver bodies still use the same AppContext-first and global fallback order. ## Handoff Notes -- Next migration slice can add another low-risk read-only background status - surface while keeping worker lifecycle mutations out of scope. -- Keep scanner, heal, lifecycle, replication, disk health, and config reload - behavior changes out of broad controller movement until each has dedicated - status snapshots. +- CTX-002 should add resolver compatibility tests before moving consumers. +- CTX-003 should protect IAM degraded-readiness publication before boot + extraction. diff --git a/rustfs/src/app/context.rs b/rustfs/src/app/context.rs index 992a7a4ff..badc6f85b 100644 --- a/rustfs/src/app/context.rs +++ b/rustfs/src/app/context.rs @@ -16,388 +16,12 @@ //! This module introduces explicit dependency injection entry points //! for storage, IAM, and KMS handles. -use crate::config::{RustFSBufferConfig, get_global_buffer_config}; -use async_trait::async_trait; -use rustfs_config::server_config::Config; -use rustfs_config::server_config::get_global_server_config; -use rustfs_ecstore::bucket::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys}; -use rustfs_ecstore::endpoints::EndpointServerPools; -use rustfs_ecstore::global::{get_global_endpoints_opt, get_global_region, get_global_tier_config_mgr}; -use rustfs_ecstore::store::ECStore; -use rustfs_ecstore::tier::tier::TierConfigMgr; -use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; -use rustfs_kms::{KmsServiceManager, get_global_kms_service_manager}; -use rustfs_notify::{EventArgs, NotificationError, notifier_global}; -use rustfs_targets::{EventName, arn::TargetID}; -use std::sync::{Arc, OnceLock}; -use tokio::sync::RwLock; - -/// IAM interface for application-layer use-cases. -pub trait IamInterface: Send + Sync { - #[allow(dead_code)] - fn handle(&self) -> Arc>; - fn is_ready(&self) -> bool; -} - -/// KMS interface for application-layer use-cases. -#[allow(dead_code)] -pub trait KmsInterface: Send + Sync { - fn handle(&self) -> Arc; -} - -/// KMS runtime interface for application-layer and admin handler integration. -pub trait KmsRuntimeInterface: Send + Sync { - fn service_manager(&self) -> Option>; -} - -/// Notify interface for application-layer use-cases. -#[async_trait] -pub trait NotifyInterface: Send + Sync { - async fn notify(&self, args: EventArgs); - - async fn add_event_specific_rules( - &self, - bucket_name: &str, - region: &str, - event_rules: &[(Vec, String, String, Vec)], - ) -> Result<(), NotificationError>; - - async fn clear_bucket_notification_rules(&self, bucket_name: &str) -> Result<(), NotificationError>; -} - -/// Bucket metadata interface for application-layer use-cases. -pub trait BucketMetadataInterface: Send + Sync { - fn handle(&self) -> Option>>; -} - -/// Endpoints interface for application-layer use-cases. -pub trait EndpointsInterface: Send + Sync { - fn handle(&self) -> Option; -} - -/// Region interface for application-layer use-cases. -pub trait RegionInterface: Send + Sync { - fn get(&self) -> Option; -} - -/// Tier config interface for application-layer and admin handlers. -pub trait TierConfigInterface: Send + Sync { - fn handle(&self) -> Arc>; -} - -/// Server config interface for application-layer and server modules. -pub trait ServerConfigInterface: Send + Sync { - fn get(&self) -> Option; -} - -/// Buffer profile config interface for application-layer use-cases. -pub trait BufferConfigInterface: Send + Sync { - fn get(&self) -> RustFSBufferConfig; -} - -/// Default IAM interface adapter. -pub struct IamHandle { - #[allow(dead_code)] - iam: Arc>, -} - -impl IamHandle { - pub fn new(iam: Arc>) -> Self { - Self { iam } - } -} - -impl IamInterface for IamHandle { - fn handle(&self) -> Arc> { - self.iam.clone() - } - - fn is_ready(&self) -> bool { - rustfs_iam::get().is_ok() - } -} - -/// Default KMS interface adapter. -#[allow(dead_code)] -pub struct KmsHandle { - kms: Arc, -} - -impl KmsHandle { - pub fn new(kms: Arc) -> Self { - Self { kms } - } -} - -impl KmsInterface for KmsHandle { - fn handle(&self) -> Arc { - self.kms.clone() - } -} - -/// Default KMS runtime interface adapter. -#[derive(Default)] -pub struct KmsRuntimeHandle; - -impl KmsRuntimeInterface for KmsRuntimeHandle { - fn service_manager(&self) -> Option> { - get_global_kms_service_manager() - } -} - -/// Default notify interface adapter. -#[derive(Default)] -pub struct NotifyHandle; - -#[async_trait] -impl NotifyInterface for NotifyHandle { - async fn notify(&self, args: EventArgs) { - notifier_global::notify(args).await; - } - - async fn add_event_specific_rules( - &self, - bucket_name: &str, - region: &str, - event_rules: &[(Vec, String, String, Vec)], - ) -> Result<(), NotificationError> { - notifier_global::add_event_specific_rules(bucket_name, region, event_rules).await - } - - async fn clear_bucket_notification_rules(&self, bucket_name: &str) -> Result<(), NotificationError> { - notifier_global::clear_bucket_notification_rules(bucket_name).await - } -} - -/// Default bucket metadata interface adapter. -#[derive(Default)] -pub struct BucketMetadataHandle; - -impl BucketMetadataInterface for BucketMetadataHandle { - fn handle(&self) -> Option>> { - get_global_bucket_metadata_sys() - } -} - -/// Default endpoints interface adapter. -#[derive(Default)] -pub struct EndpointsHandle; - -impl EndpointsInterface for EndpointsHandle { - fn handle(&self) -> Option { - get_global_endpoints_opt() - } -} - -/// Default region interface adapter. -#[derive(Default)] -pub struct RegionHandle; - -impl RegionInterface for RegionHandle { - fn get(&self) -> Option { - get_global_region() - } -} - -/// Default tier config interface adapter. -#[derive(Default)] -pub struct TierConfigHandle; - -impl TierConfigInterface for TierConfigHandle { - fn handle(&self) -> Arc> { - get_global_tier_config_mgr() - } -} - -/// Default server config interface adapter. -#[derive(Default)] -pub struct ServerConfigHandle; - -impl ServerConfigInterface for ServerConfigHandle { - fn get(&self) -> Option { - get_global_server_config() - } -} - -/// Default buffer profile config interface adapter. -#[derive(Default)] -pub struct BufferConfigHandle; - -impl BufferConfigInterface for BufferConfigHandle { - fn get(&self) -> RustFSBufferConfig { - get_global_buffer_config().clone() - } -} - -/// Application-layer context with explicit dependencies. -#[derive(Clone)] -pub struct AppContext { - object_store: Arc, - iam: Arc, - #[allow(dead_code)] - kms: Arc, - kms_runtime: Arc, - notify: Arc, - bucket_metadata: Arc, - endpoints: Arc, - region: Arc, - tier_config: Arc, - server_config: Arc, - buffer_config: Arc, -} - -impl AppContext { - pub fn new(object_store: Arc, iam: Arc, kms: Arc) -> Self { - Self { - object_store, - iam, - kms, - kms_runtime: default_kms_runtime_interface(), - notify: default_notify_interface(), - bucket_metadata: default_bucket_metadata_interface(), - endpoints: default_endpoints_interface(), - region: default_region_interface(), - tier_config: default_tier_config_interface(), - server_config: default_server_config_interface(), - buffer_config: default_buffer_config_interface(), - } - } - - pub fn with_default_interfaces( - object_store: Arc, - iam: Arc>, - kms: Arc, - ) -> Self { - Self::new(object_store, Arc::new(IamHandle::new(iam)), Arc::new(KmsHandle::new(kms))) - } - - pub fn object_store(&self) -> Arc { - self.object_store.clone() - } - - pub fn iam(&self) -> Arc { - self.iam.clone() - } - - #[allow(dead_code)] - pub fn kms(&self) -> Arc { - self.kms.clone() - } - - pub fn kms_runtime(&self) -> Arc { - self.kms_runtime.clone() - } - - pub fn notify(&self) -> Arc { - self.notify.clone() - } - - pub fn bucket_metadata(&self) -> Arc { - self.bucket_metadata.clone() - } - - pub fn endpoints(&self) -> Arc { - self.endpoints.clone() - } - - pub fn region(&self) -> Arc { - self.region.clone() - } - - pub fn tier_config(&self) -> Arc { - self.tier_config.clone() - } - - pub fn server_config(&self) -> Arc { - self.server_config.clone() - } - - pub fn buffer_config(&self) -> Arc { - self.buffer_config.clone() - } -} - -pub fn default_notify_interface() -> Arc { - Arc::new(NotifyHandle) -} - -pub fn default_kms_runtime_interface() -> Arc { - Arc::new(KmsRuntimeHandle) -} - -/// Resolve KMS runtime service manager using AppContext-first precedence. -pub fn resolve_kms_runtime_service_manager() -> Option> { - get_global_app_context() - .and_then(|context| context.kms_runtime().service_manager()) - .or_else(|| default_kms_runtime_interface().service_manager()) -} - -/// Resolve bucket metadata handle using AppContext-first precedence. -pub fn resolve_bucket_metadata_handle() -> Option>> { - get_global_app_context() - .and_then(|context| context.bucket_metadata().handle()) - .or_else(|| default_bucket_metadata_interface().handle()) -} - -/// Resolve object store handle from AppContext. -pub fn resolve_object_store_handle() -> Option> { - get_global_app_context().map(|context| context.object_store()) -} - -/// Resolve endpoints using AppContext-first precedence. -pub fn resolve_endpoints_handle() -> Option { - get_global_app_context() - .and_then(|context| context.endpoints().handle()) - .or_else(|| default_endpoints_interface().handle()) -} - -/// Resolve tier config handle using AppContext-first precedence. -pub fn resolve_tier_config_handle() -> Arc> { - get_global_app_context() - .map(|context| context.tier_config().handle()) - .unwrap_or_else(|| default_tier_config_interface().handle()) -} - -/// Resolve server config using AppContext-first precedence. -pub fn resolve_server_config() -> Option { - match get_global_app_context() { - Some(context) => context.server_config().get(), - None => default_server_config_interface().get(), - } -} - -pub fn default_bucket_metadata_interface() -> Arc { - Arc::new(BucketMetadataHandle) -} - -pub fn default_endpoints_interface() -> Arc { - Arc::new(EndpointsHandle) -} - -pub fn default_region_interface() -> Arc { - Arc::new(RegionHandle) -} - -pub fn default_tier_config_interface() -> Arc { - Arc::new(TierConfigHandle) -} - -pub fn default_server_config_interface() -> Arc { - Arc::new(ServerConfigHandle) -} - -pub fn default_buffer_config_interface() -> Arc { - Arc::new(BufferConfigHandle) -} - -static APP_CONTEXT_SINGLETON: OnceLock> = OnceLock::new(); - -/// Initialize global application context once and return the canonical instance. -pub fn init_global_app_context(context: AppContext) -> Arc { - APP_CONTEXT_SINGLETON.get_or_init(|| Arc::new(context)).clone() -} - -/// Get global application context if it has been initialized. -pub fn get_global_app_context() -> Option> { - APP_CONTEXT_SINGLETON.get().cloned() -} +mod compat; +mod global; +mod handles; +mod interfaces; + +pub use compat::*; +pub use global::*; +pub use handles::*; +pub use interfaces::*; diff --git a/rustfs/src/app/context/compat.rs b/rustfs/src/app/context/compat.rs new file mode 100644 index 000000000..b511311d2 --- /dev/null +++ b/rustfs/src/app/context/compat.rs @@ -0,0 +1,68 @@ +// 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::global::get_global_app_context; +use super::handles::{ + default_bucket_metadata_interface, default_endpoints_interface, default_kms_runtime_interface, + default_server_config_interface, default_tier_config_interface, +}; +use rustfs_config::server_config::Config; +use rustfs_ecstore::bucket::metadata_sys::BucketMetadataSys; +use rustfs_ecstore::endpoints::EndpointServerPools; +use rustfs_ecstore::store::ECStore; +use rustfs_ecstore::tier::tier::TierConfigMgr; +use rustfs_kms::KmsServiceManager; +use std::sync::Arc; +use tokio::sync::RwLock; + +/// Resolve KMS runtime service manager using AppContext-first precedence. +pub fn resolve_kms_runtime_service_manager() -> Option> { + get_global_app_context() + .and_then(|context| context.kms_runtime().service_manager()) + .or_else(|| default_kms_runtime_interface().service_manager()) +} + +/// Resolve bucket metadata handle using AppContext-first precedence. +pub fn resolve_bucket_metadata_handle() -> Option>> { + get_global_app_context() + .and_then(|context| context.bucket_metadata().handle()) + .or_else(|| default_bucket_metadata_interface().handle()) +} + +/// Resolve object store handle from AppContext. +pub fn resolve_object_store_handle() -> Option> { + get_global_app_context().map(|context| context.object_store()) +} + +/// Resolve endpoints using AppContext-first precedence. +pub fn resolve_endpoints_handle() -> Option { + get_global_app_context() + .and_then(|context| context.endpoints().handle()) + .or_else(|| default_endpoints_interface().handle()) +} + +/// Resolve tier config handle using AppContext-first precedence. +pub fn resolve_tier_config_handle() -> Arc> { + get_global_app_context() + .map(|context| context.tier_config().handle()) + .unwrap_or_else(|| default_tier_config_interface().handle()) +} + +/// Resolve server config using AppContext-first precedence. +pub fn resolve_server_config() -> Option { + match get_global_app_context() { + Some(context) => context.server_config().get(), + None => default_server_config_interface().get(), + } +} diff --git a/rustfs/src/app/context/global.rs b/rustfs/src/app/context/global.rs new file mode 100644 index 000000000..66bc1f052 --- /dev/null +++ b/rustfs/src/app/context/global.rs @@ -0,0 +1,127 @@ +// 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::handles::{ + IamHandle, KmsHandle, default_bucket_metadata_interface, default_buffer_config_interface, default_endpoints_interface, + default_kms_runtime_interface, default_notify_interface, default_region_interface, default_server_config_interface, + default_tier_config_interface, +}; +use super::interfaces::{ + BucketMetadataInterface, BufferConfigInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, + NotifyInterface, RegionInterface, ServerConfigInterface, TierConfigInterface, +}; +use rustfs_ecstore::store::ECStore; +use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; +use rustfs_kms::KmsServiceManager; +use std::sync::{Arc, OnceLock}; + +/// Application-layer context with explicit dependencies. +#[derive(Clone)] +pub struct AppContext { + object_store: Arc, + iam: Arc, + #[allow(dead_code)] + kms: Arc, + kms_runtime: Arc, + notify: Arc, + bucket_metadata: Arc, + endpoints: Arc, + region: Arc, + tier_config: Arc, + server_config: Arc, + buffer_config: Arc, +} + +impl AppContext { + pub fn new(object_store: Arc, iam: Arc, kms: Arc) -> Self { + Self { + object_store, + iam, + kms, + kms_runtime: default_kms_runtime_interface(), + notify: default_notify_interface(), + bucket_metadata: default_bucket_metadata_interface(), + endpoints: default_endpoints_interface(), + region: default_region_interface(), + tier_config: default_tier_config_interface(), + server_config: default_server_config_interface(), + buffer_config: default_buffer_config_interface(), + } + } + + pub fn with_default_interfaces( + object_store: Arc, + iam: Arc>, + kms: Arc, + ) -> Self { + Self::new(object_store, Arc::new(IamHandle::new(iam)), Arc::new(KmsHandle::new(kms))) + } + + pub fn object_store(&self) -> Arc { + self.object_store.clone() + } + + pub fn iam(&self) -> Arc { + self.iam.clone() + } + + #[allow(dead_code)] + pub fn kms(&self) -> Arc { + self.kms.clone() + } + + pub fn kms_runtime(&self) -> Arc { + self.kms_runtime.clone() + } + + pub fn notify(&self) -> Arc { + self.notify.clone() + } + + pub fn bucket_metadata(&self) -> Arc { + self.bucket_metadata.clone() + } + + pub fn endpoints(&self) -> Arc { + self.endpoints.clone() + } + + pub fn region(&self) -> Arc { + self.region.clone() + } + + pub fn tier_config(&self) -> Arc { + self.tier_config.clone() + } + + pub fn server_config(&self) -> Arc { + self.server_config.clone() + } + + pub fn buffer_config(&self) -> Arc { + self.buffer_config.clone() + } +} + +static APP_CONTEXT_SINGLETON: OnceLock> = OnceLock::new(); + +/// Initialize global application context once and return the canonical instance. +pub fn init_global_app_context(context: AppContext) -> Arc { + APP_CONTEXT_SINGLETON.get_or_init(|| Arc::new(context)).clone() +} + +/// Get global application context if it has been initialized. +pub fn get_global_app_context() -> Option> { + APP_CONTEXT_SINGLETON.get().cloned() +} diff --git a/rustfs/src/app/context/handles.rs b/rustfs/src/app/context/handles.rs new file mode 100644 index 000000000..2324880f0 --- /dev/null +++ b/rustfs/src/app/context/handles.rs @@ -0,0 +1,198 @@ +// 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::interfaces::{ + BucketMetadataInterface, BufferConfigInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, + NotifyInterface, RegionInterface, ServerConfigInterface, TierConfigInterface, +}; +use crate::config::{RustFSBufferConfig, get_global_buffer_config}; +use async_trait::async_trait; +use rustfs_config::server_config::Config; +use rustfs_config::server_config::get_global_server_config; +use rustfs_ecstore::bucket::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys}; +use rustfs_ecstore::endpoints::EndpointServerPools; +use rustfs_ecstore::global::{get_global_endpoints_opt, get_global_region, get_global_tier_config_mgr}; +use rustfs_ecstore::tier::tier::TierConfigMgr; +use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; +use rustfs_kms::{KmsServiceManager, get_global_kms_service_manager}; +use rustfs_notify::{EventArgs, NotificationError, notifier_global}; +use rustfs_targets::{EventName, arn::TargetID}; +use std::sync::Arc; +use tokio::sync::RwLock; + +/// Default IAM interface adapter. +pub struct IamHandle { + #[allow(dead_code)] + iam: Arc>, +} + +impl IamHandle { + pub fn new(iam: Arc>) -> Self { + Self { iam } + } +} + +impl IamInterface for IamHandle { + fn handle(&self) -> Arc> { + self.iam.clone() + } + + fn is_ready(&self) -> bool { + rustfs_iam::get().is_ok() + } +} + +/// Default KMS interface adapter. +#[allow(dead_code)] +pub struct KmsHandle { + kms: Arc, +} + +impl KmsHandle { + pub fn new(kms: Arc) -> Self { + Self { kms } + } +} + +impl KmsInterface for KmsHandle { + fn handle(&self) -> Arc { + self.kms.clone() + } +} + +/// Default KMS runtime interface adapter. +#[derive(Default)] +pub struct KmsRuntimeHandle; + +impl KmsRuntimeInterface for KmsRuntimeHandle { + fn service_manager(&self) -> Option> { + get_global_kms_service_manager() + } +} + +/// Default notify interface adapter. +#[derive(Default)] +pub struct NotifyHandle; + +#[async_trait] +impl NotifyInterface for NotifyHandle { + async fn notify(&self, args: EventArgs) { + notifier_global::notify(args).await; + } + + async fn add_event_specific_rules( + &self, + bucket_name: &str, + region: &str, + event_rules: &[(Vec, String, String, Vec)], + ) -> Result<(), NotificationError> { + notifier_global::add_event_specific_rules(bucket_name, region, event_rules).await + } + + async fn clear_bucket_notification_rules(&self, bucket_name: &str) -> Result<(), NotificationError> { + notifier_global::clear_bucket_notification_rules(bucket_name).await + } +} + +/// Default bucket metadata interface adapter. +#[derive(Default)] +pub struct BucketMetadataHandle; + +impl BucketMetadataInterface for BucketMetadataHandle { + fn handle(&self) -> Option>> { + get_global_bucket_metadata_sys() + } +} + +/// Default endpoints interface adapter. +#[derive(Default)] +pub struct EndpointsHandle; + +impl EndpointsInterface for EndpointsHandle { + fn handle(&self) -> Option { + get_global_endpoints_opt() + } +} + +/// Default region interface adapter. +#[derive(Default)] +pub struct RegionHandle; + +impl RegionInterface for RegionHandle { + fn get(&self) -> Option { + get_global_region() + } +} + +/// Default tier config interface adapter. +#[derive(Default)] +pub struct TierConfigHandle; + +impl TierConfigInterface for TierConfigHandle { + fn handle(&self) -> Arc> { + get_global_tier_config_mgr() + } +} + +/// Default server config interface adapter. +#[derive(Default)] +pub struct ServerConfigHandle; + +impl ServerConfigInterface for ServerConfigHandle { + fn get(&self) -> Option { + get_global_server_config() + } +} + +/// Default buffer profile config interface adapter. +#[derive(Default)] +pub struct BufferConfigHandle; + +impl BufferConfigInterface for BufferConfigHandle { + fn get(&self) -> RustFSBufferConfig { + get_global_buffer_config().clone() + } +} + +pub fn default_notify_interface() -> Arc { + Arc::new(NotifyHandle) +} + +pub fn default_kms_runtime_interface() -> Arc { + Arc::new(KmsRuntimeHandle) +} + +pub fn default_bucket_metadata_interface() -> Arc { + Arc::new(BucketMetadataHandle) +} + +pub fn default_endpoints_interface() -> Arc { + Arc::new(EndpointsHandle) +} + +pub fn default_region_interface() -> Arc { + Arc::new(RegionHandle) +} + +pub fn default_tier_config_interface() -> Arc { + Arc::new(TierConfigHandle) +} + +pub fn default_server_config_interface() -> Arc { + Arc::new(ServerConfigHandle) +} + +pub fn default_buffer_config_interface() -> Arc { + Arc::new(BufferConfigHandle) +} diff --git a/rustfs/src/app/context/interfaces.rs b/rustfs/src/app/context/interfaces.rs new file mode 100644 index 000000000..7658ddc29 --- /dev/null +++ b/rustfs/src/app/context/interfaces.rs @@ -0,0 +1,89 @@ +// 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 crate::config::RustFSBufferConfig; +use async_trait::async_trait; +use rustfs_config::server_config::Config; +use rustfs_ecstore::bucket::metadata_sys::BucketMetadataSys; +use rustfs_ecstore::endpoints::EndpointServerPools; +use rustfs_ecstore::tier::tier::TierConfigMgr; +use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; +use rustfs_kms::KmsServiceManager; +use rustfs_notify::{EventArgs, NotificationError}; +use rustfs_targets::{EventName, arn::TargetID}; +use std::sync::Arc; +use tokio::sync::RwLock; + +/// IAM interface for application-layer use-cases. +pub trait IamInterface: Send + Sync { + #[allow(dead_code)] + fn handle(&self) -> Arc>; + fn is_ready(&self) -> bool; +} + +/// KMS interface for application-layer use-cases. +#[allow(dead_code)] +pub trait KmsInterface: Send + Sync { + fn handle(&self) -> Arc; +} + +/// KMS runtime interface for application-layer and admin handler integration. +pub trait KmsRuntimeInterface: Send + Sync { + fn service_manager(&self) -> Option>; +} + +/// Notify interface for application-layer use-cases. +#[async_trait] +pub trait NotifyInterface: Send + Sync { + async fn notify(&self, args: EventArgs); + + async fn add_event_specific_rules( + &self, + bucket_name: &str, + region: &str, + event_rules: &[(Vec, String, String, Vec)], + ) -> Result<(), NotificationError>; + + async fn clear_bucket_notification_rules(&self, bucket_name: &str) -> Result<(), NotificationError>; +} + +/// Bucket metadata interface for application-layer use-cases. +pub trait BucketMetadataInterface: Send + Sync { + fn handle(&self) -> Option>>; +} + +/// Endpoints interface for application-layer use-cases. +pub trait EndpointsInterface: Send + Sync { + fn handle(&self) -> Option; +} + +/// Region interface for application-layer use-cases. +pub trait RegionInterface: Send + Sync { + fn get(&self) -> Option; +} + +/// Tier config interface for application-layer and admin handlers. +pub trait TierConfigInterface: Send + Sync { + fn handle(&self) -> Arc>; +} + +/// Server config interface for application-layer and server modules. +pub trait ServerConfigInterface: Send + Sync { + fn get(&self) -> Option; +} + +/// Buffer profile config interface for application-layer use-cases. +pub trait BufferConfigInterface: Send + Sync { + fn get(&self) -> RustFSBufferConfig; +}