Skip to main content

systemprompt_database/scope/
registry.rs

1//! Inventory-based registration for [`ConnectionScopeProvider`]s.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use std::sync::OnceLock;
7
8use super::provider::SharedScopeProvider;
9
10/// One inventory submission per [`crate::register_scope_provider!`] call.
11#[derive(Debug, Clone, Copy)]
12pub struct ScopeProviderRegistration {
13    pub factory: fn() -> SharedScopeProvider,
14}
15
16inventory::collect!(ScopeProviderRegistration);
17
18/// Construct every registered provider, in collection order.
19#[must_use]
20pub fn discover_scope_providers() -> Vec<SharedScopeProvider> {
21    inventory::iter::<ScopeProviderRegistration>()
22        .map(|reg| (reg.factory)())
23        .collect()
24}
25
26/// The process-wide provider list, constructed once on first use. An empty
27/// slice (no extension registered) keeps every scoped-transaction call a
28/// plain `pool.begin()`.
29#[must_use]
30pub fn scope_providers() -> &'static [SharedScopeProvider] {
31    static PROVIDERS: OnceLock<Vec<SharedScopeProvider>> = OnceLock::new();
32    PROVIDERS.get_or_init(discover_scope_providers)
33}
34
35/// Register a [`super::ConnectionScopeProvider`] factory at static-init time.
36///
37/// Wire alongside `register_extension!` in the extension's `extension.rs`:
38///
39/// ```ignore
40/// systemprompt_database::register_scope_provider!(|| {
41///     std::sync::Arc::new(OrgScopeProvider)
42///         as systemprompt_database::scope::SharedScopeProvider
43/// });
44/// ```
45#[macro_export]
46macro_rules! register_scope_provider {
47    ($factory:expr) => {
48        ::inventory::submit! {
49            $crate::scope::ScopeProviderRegistration {
50                factory: $factory,
51            }
52        }
53    };
54}