This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new b9a78ac33 refactor(core): allow opt-out ctor dependency (#7196)
b9a78ac33 is described below

commit b9a78ac3304d0872b089eb6621466035951ec1c2
Author: tison <[email protected]>
AuthorDate: Sun Feb 22 13:47:19 2026 +0800

    refactor(core): allow opt-out ctor dependency (#7196)
    
    * refactor(core): allow opt-out ctor dependency
    
    Signed-off-by: tison <[email protected]>
    
    * fixup
    
    Signed-off-by: tison <[email protected]>
    
    * rename feature
    
    Signed-off-by: tison <[email protected]>
    
    ---------
    
    Signed-off-by: tison <[email protected]>
---
 core/Cargo.toml                          |  5 +++-
 core/core/src/types/mod.rs               |  1 -
 core/core/src/types/operator/builder.rs  |  2 +-
 core/core/src/types/operator/mod.rs      |  2 +-
 core/core/src/types/operator/registry.rs | 42 +++++++++++++++-----------------
 core/src/lib.rs                          | 13 ++++------
 6 files changed, 30 insertions(+), 35 deletions(-)

diff --git a/core/Cargo.toml b/core/Cargo.toml
index f1a19d950..93be3579f 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -81,8 +81,11 @@ unused_async = "warn"
 all-features = true
 
 [features]
+# Register services enabled to the OperatorRegistry so that they can be used 
by `Operator::from_uri`.
+auto-register-services = ["dep:ctor"]
 blocking = ["opendal-core/blocking"]
 default = [
+  "auto-register-services",
   "reqwest-rustls-tls",
   "executors-tokio",
   "layers-concurrent-limit",
@@ -207,7 +210,7 @@ path = "tests/behavior/main.rs"
 required-features = ["tests"]
 
 [dependencies]
-ctor = { workspace = true }
+ctor = { workspace = true, optional = true }
 opendal-core = { path = "core", version = "0.55.0", default-features = false }
 opendal-layer-async-backtrace = { path = "layers/async-backtrace", version = 
"0.55.0", optional = true, default-features = false }
 opendal-layer-await-tree = { path = "layers/await-tree", version = "0.55.0", 
optional = true, default-features = false }
diff --git a/core/core/src/types/mod.rs b/core/core/src/types/mod.rs
index fb168553f..8042804ae 100644
--- a/core/core/src/types/mod.rs
+++ b/core/core/src/types/mod.rs
@@ -43,7 +43,6 @@ mod execute;
 pub use execute::*;
 
 mod operator;
-pub use operator::DEFAULT_OPERATOR_REGISTRY;
 pub use operator::IntoOperatorUri;
 pub use operator::Operator;
 pub use operator::OperatorBuilder;
diff --git a/core/core/src/types/operator/builder.rs 
b/core/core/src/types/operator/builder.rs
index 195006a8b..201f87612 100644
--- a/core/core/src/types/operator/builder.rs
+++ b/core/core/src/types/operator/builder.rs
@@ -142,7 +142,7 @@ impl Operator {
     /// # }
     /// ```
     pub fn from_uri(uri: impl IntoOperatorUri) -> Result<Operator> {
-        crate::DEFAULT_OPERATOR_REGISTRY.load(uri)
+        OperatorRegistry::get().load(uri)
     }
 
     /// Create a new operator via given scheme and iterator of config value in 
dynamic dispatch.
diff --git a/core/core/src/types/operator/mod.rs 
b/core/core/src/types/operator/mod.rs
index 3de1ea7c1..7dba388e5 100644
--- a/core/core/src/types/operator/mod.rs
+++ b/core/core/src/types/operator/mod.rs
@@ -30,7 +30,7 @@ pub use info::OperatorInfo;
 pub mod operator_futures;
 
 mod registry;
-pub use registry::{DEFAULT_OPERATOR_REGISTRY, OperatorFactory, 
OperatorRegistry};
+pub use registry::{OperatorFactory, OperatorRegistry};
 
 mod uri;
 pub use uri::{IntoOperatorUri, OperatorUri};
diff --git a/core/core/src/types/operator/registry.rs 
b/core/core/src/types/operator/registry.rs
index dc10beb5e..d95a681ec 100644
--- a/core/core/src/types/operator/registry.rs
+++ b/core/core/src/types/operator/registry.rs
@@ -15,42 +15,38 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::collections::HashMap;
-use std::sync::{LazyLock, Mutex};
-
 use crate::types::builder::{Builder, Configurator};
 use crate::types::{IntoOperatorUri, OperatorUri};
 use crate::{Error, ErrorKind, Operator, Result};
+use std::collections::HashMap;
+use std::sync::{LazyLock, Mutex};
 
 /// Factory signature used to construct [`Operator`] from a URI and extra 
options.
 pub type OperatorFactory = fn(&OperatorUri) -> Result<Operator>;
 
-/// Default registry used by [`Operator::from_uri`].
-///
-/// `memory` is always registered here since it's used pervasively in unit 
tests
-/// and as a zero-dependency backend.
-///
-/// Other optional service registrations are handled by the facade crate 
`opendal`.
-pub static DEFAULT_OPERATOR_REGISTRY: LazyLock<OperatorRegistry> = 
LazyLock::new(|| {
-    let registry = OperatorRegistry::new();
-
-    crate::services::register_memory_service(&registry);
-
-    registry
-});
-
 /// Global registry that maps schemes to [`OperatorFactory`] functions.
-#[derive(Debug, Default)]
+#[derive(Debug)]
 pub struct OperatorRegistry {
     factories: Mutex<HashMap<String, OperatorFactory>>,
 }
 
 impl OperatorRegistry {
-    /// Create a new, empty registry.
-    pub fn new() -> Self {
-        Self {
-            factories: Mutex::new(HashMap::new()),
-        }
+    /// Get the global registry.
+    pub fn get() -> &'static Self {
+        /// The global registry used by [`Operator::from_uri`].
+        ///
+        /// `memory` is always registered here since it's used pervasively in 
unit tests
+        /// and as a zero-dependency backend.
+        ///
+        /// Other optional service registrations are handled by the facade 
crate `opendal`.
+        static OPERATOR_REGISTRY: LazyLock<OperatorRegistry> = 
LazyLock::new(|| {
+            let factories = Mutex::new(HashMap::default());
+            let registry = OperatorRegistry { factories };
+            crate::services::register_memory_service(&registry);
+            registry
+        });
+
+        &OPERATOR_REGISTRY
     }
 
     /// Register a builder for the given scheme.
diff --git a/core/src/lib.rs b/core/src/lib.rs
index 5563bd712..f3e7a3bc2 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -27,9 +27,7 @@ pub use opendal_core::*;
 #[cfg(feature = "tests")]
 pub extern crate opendal_testkit as tests;
 
-static DEFAULT_REGISTRY_INIT: std::sync::Once = std::sync::Once::new();
-
-/// Initialize [`DEFAULT_OPERATOR_REGISTRY`] with enabled services.
+/// Initialize the global [`OperatorRegistry`] with enabled services.
 ///
 /// This function is safe to call multiple times and will only perform
 /// initialization once.
@@ -41,13 +39,11 @@ static DEFAULT_REGISTRY_INIT: std::sync::Once = 
std::sync::Once::new();
 /// should call this function explicitly before using `Operator::from_uri` or
 /// `Operator::via_iter`.
 pub fn init_default_registry() {
-    DEFAULT_REGISTRY_INIT.call_once(|| {
-        let registry = &opendal_core::DEFAULT_OPERATOR_REGISTRY;
-        init_default_registry_inner(registry);
-    });
+    static DEFAULT_REGISTRY_INIT: std::sync::Once = std::sync::Once::new();
+    DEFAULT_REGISTRY_INIT.call_once(|| 
init_default_registry_inner(OperatorRegistry::get()));
 }
 
-fn init_default_registry_inner(registry: &opendal_core::OperatorRegistry) {
+fn init_default_registry_inner(registry: &OperatorRegistry) {
     opendal_core::services::register_memory_service(registry);
 
     #[cfg(feature = "services-aliyun-drive")]
@@ -234,6 +230,7 @@ fn init_default_registry_inner(registry: 
&opendal_core::OperatorRegistry) {
     opendal_service_redis::register_redis_service(registry);
 }
 
+#[cfg(feature = "auto-register-services")]
 #[ctor::ctor]
 fn register_default_operator_registry() {
     init_default_registry();

Reply via email to