mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-20 19:42:17 +00:00
359bdc0f1f
* refactor(ecstore): migrate the background-services cancel token into InstanceContext (Phase 5 Slice 13) Phase 5 Slice 13 (backlog#939): move the background-services cancellation token out of the process static into the per-instance InstanceContext, so cancelling one instance's background workers (scanner/heal/tier/lifecycle) no longer touches another instance. - InstanceContext gains `background_cancel_token: OnceLock<CancellationToken>` with `init_background_cancel_token` (set-once) and `background_cancel_token()` returning an owned clone. - global.rs `init_/get_/create_/shutdown_` helpers keep their signatures and route through the current instance's context; the static is removed. The getter now returns an owned `Option<CancellationToken>` instead of a `Option<&'static _>`, which is what lets the token live in the context. - Callers adapt to the owned token: the metadata-refresh loop drops `.cloned()`; the lifecycle worker/loops take the owned token (a shared fallback is cloned when the token is somehow uninitialized). No Arc cycle is introduced — workers hold a token clone, not the instance context. Single-instance behavior is unchanged: startup creates one token in the bootstrap context the ECStore adopts, and shutdown cancels that same token. Tests: the token is set-once and cancelling one instance's token leaves a distinct instance uninitialized. Verification: cargo test -p rustfs-ecstore (23 instance-context tests green), cargo clippy -p rustfs-ecstore --all-targets (clean), make pre-commit (pass). Refs: backlog#939 (Phase 5, Slice 13) * test(ecstore): prove multi-instance isolation; document embedded guard retention (Phase 5 Slice 14) (#4588) Phase 5 (backlog#939) capstone. The prior 13 slices moved every piece of per-instance runtime state out of process globals into ECStore's InstanceContext. This slice proves the result and records the remaining work. - Add `two_instances_isolate_all_migrated_state`: an end-to-end acceptance test that constructs two independent InstanceContexts and verifies NONE of the migrated state is shared — erasure setup, lock manager, region, deployment id, the four service handles (tier/notifier/expiry/transition), the local disk registry, the bucket monitor, and the background cancel token. This is the object-graph isolation carrier working end to end. - Document why the embedded single-instance guard (EMBEDDED_SERVER_STARTED) is intentionally retained: storage startup still publishes into the process-level bootstrap context (write-once region/endpoints/deployment id) and the single GLOBAL_OBJECT_API handle, so a second startup would fail-fast on that shared state. Lifting the guard requires threading a per-instance context through startup — a follow-up beyond migrating the globals. The guard is NOT removed: rejecting the second start is safer than the panic it would otherwise become. Verification: cargo test -p rustfs-ecstore (acceptance test + all instance-context tests green), cargo clippy -p rustfs-ecstore --all-targets (clean), make pre-commit (pass). Refs: backlog#939 (Phase 5, Slice 14). Stacked on Slice 13 (#4586).
57 lines
1.8 KiB
Rust
57 lines
1.8 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 std::sync::Arc;
|
|
|
|
use s3s::dto::BucketLifecycleConfiguration;
|
|
use tokio::sync::RwLock;
|
|
use tokio_util::sync::CancellationToken;
|
|
|
|
use crate::bucket::lifecycle::bucket_lifecycle_ops::{ExpiryState, TransitionState};
|
|
use crate::runtime::sources;
|
|
use crate::services::tier::tier::TierConfigMgr;
|
|
use crate::store::ECStore;
|
|
|
|
pub(crate) fn expiry_state_handle() -> Arc<RwLock<ExpiryState>> {
|
|
sources::expiry_state_handle()
|
|
}
|
|
|
|
pub(crate) fn transition_state_handle() -> Arc<TransitionState> {
|
|
sources::transition_state_handle()
|
|
}
|
|
|
|
pub(crate) fn tier_config_mgr_handle() -> Arc<RwLock<TierConfigMgr>> {
|
|
sources::tier_config_mgr_handle()
|
|
}
|
|
|
|
pub(crate) fn background_services_cancel_token() -> Option<CancellationToken> {
|
|
sources::background_services_cancel_token()
|
|
}
|
|
|
|
pub(crate) fn object_store_handle() -> Option<Arc<ECStore>> {
|
|
sources::object_store_handle()
|
|
}
|
|
|
|
pub(crate) fn default_local_node_name() -> String {
|
|
sources::default_local_node_name()
|
|
}
|
|
|
|
pub(crate) fn deployment_id() -> Option<String> {
|
|
sources::deployment_id()
|
|
}
|
|
|
|
pub(crate) async fn bucket_lifecycle_config(bucket: &str) -> Option<BucketLifecycleConfiguration> {
|
|
sources::bucket_lifecycle_config(bucket).await
|
|
}
|