refactor(app): per-context server-config handle and Arc-owned notification system (#4621)

* refactor(app): give each context's server-config handle its own copy

backlog#1052 S3, first slice: establish the per-context state pattern on
the smallest subsystem. ServerConfigHandle was a unit struct forwarding
both get and set to the process-global GLOBAL_SERVER_CONFIG, so every
AppContext shared one config regardless of which context a caller held.

The handle now keeps its own copy: a set lands on the owning context and
on the process global (ambient readers — the config loader path, the
scanner — keep working), and a get prefers the owned copy, falling back
to the global while the initial load still publishes there. Single
instance: the owned copy and the global are written together, so reads
are unchanged. Two contexts that both published stay isolated even though
the shared global only remembers the last write (covered by a new test).

The global write in set() is the transitional bridge for ambient readers;
it goes away when those readers migrate and multi-instance flips on
(backlog#1052 S5).

* refactor(notify): hand out the notification system as an owned Arc

backlog#1052 S3, second slice. GLOBAL_NOTIFICATION_SYS stored the
NotificationSys by value and every accessor returned
Option<&'static NotificationSys> — a process-lifetime borrow that a
per-server AppContext can never hold. The global now stores an Arc and
the accessor chain (ecstore runtime sources, ECStore::notification_system,
the iam forwarders, the rustfs shims, NotificationSystemInterface and the
AppContext resolvers) hands out owned Arcs instead.

Call sites are unchanged apart from two borrow adjustments in the
rebalance admin handler (pass &Arc where a reference is expected; borrow
with as_ref() so the handle survives to the second use). Behavior is
identical — same single global instance, first init still wins — but the
type now permits a future per-server context to own its notification
system (backlog#1052 S3 follow-up).
This commit is contained in:
Zhengchao An
2026-07-09 20:07:09 +08:00
committed by GitHub
parent 90c0deff58
commit 476352106e
13 changed files with 76 additions and 22 deletions
+1 -1
View File
@@ -306,7 +306,7 @@ pub(crate) async fn publish_object_store(store: Arc<ECStore>) {
set_object_layer(store).await;
}
pub(crate) fn notification_sys() -> Option<&'static NotificationSys> {
pub(crate) fn notification_sys() -> Option<Arc<NotificationSys>> {
get_global_notification_sys()
}
@@ -31,7 +31,7 @@ use rustfs_utils::XHost;
use std::collections::hash_map::DefaultHasher;
use std::future::Future;
use std::hash::{Hash, Hasher};
use std::sync::{Mutex, OnceLock};
use std::sync::{Arc, Mutex, OnceLock};
use std::time::{Duration, SystemTime};
use tokio::time::timeout;
use tracing::{debug, error, info, warn};
@@ -72,18 +72,21 @@ impl PeerAdminCache {
const SERVER_INFO_CACHE_MAX_AGE: Duration = Duration::from_secs(60);
lazy_static! {
pub static ref GLOBAL_NOTIFICATION_SYS: OnceLock<NotificationSys> = OnceLock::new();
pub static ref GLOBAL_NOTIFICATION_SYS: OnceLock<Arc<NotificationSys>> = OnceLock::new();
}
pub async fn new_global_notification_sys(eps: EndpointServerPools) -> Result<()> {
let _ = GLOBAL_NOTIFICATION_SYS
.set(NotificationSys::new(eps).await)
.set(Arc::new(NotificationSys::new(eps).await))
.map_err(|_| Error::other("init notification_sys fail"));
Ok(())
}
pub fn get_global_notification_sys() -> Option<&'static NotificationSys> {
GLOBAL_NOTIFICATION_SYS.get()
// Owned handle rather than `&'static` (backlog#1052 S3): per-server contexts
// need to hold their own notification system, which a process-lifetime
// borrow cannot express.
pub fn get_global_notification_sys() -> Option<Arc<NotificationSys>> {
GLOBAL_NOTIFICATION_SYS.get().cloned()
}
pub struct NotificationSys {
+1 -1
View File
@@ -242,7 +242,7 @@ impl ECStore {
/// service singletons. The globals remain the source of truth.
impl ECStore {
/// Get the notification system
pub fn notification_system(&self) -> Option<&'static crate::services::notification_sys::NotificationSys> {
pub fn notification_system(&self) -> Option<std::sync::Arc<crate::services::notification_sys::NotificationSys>> {
runtime_sources::notification_sys()
}
+1 -1
View File
@@ -24,6 +24,6 @@ pub(crate) fn current_server_config() -> Option<ServerConfig> {
get_global_server_config()
}
pub(crate) fn notification_sys() -> Option<&'static IamNotificationSys> {
pub(crate) fn notification_sys() -> Option<std::sync::Arc<IamNotificationSys>> {
ecstore_notification_sys()
}
+1 -1
View File
@@ -77,7 +77,7 @@ pub(crate) async fn is_iam_first_cluster_node_local() -> bool {
ecstore_first_cluster_node_is_local().await
}
pub(crate) fn notification_sys() -> Option<&'static IamNotificationSys> {
pub(crate) fn notification_sys() -> Option<std::sync::Arc<IamNotificationSys>> {
get_global_notification_sys()
}