fluxdi 1.2.2

FluxDI - Semi-Automatic Dependency Injector
Documentation
use super::*;

impl Injector {
    pub(crate) fn resolve_instance<T>(&self) -> Result<Shared<Instance<T>>, Error>
    where
        T: ?Sized + 'static,
    {
        #[cfg(feature = "metrics")]
        self.inner.metrics.record_factory_execution();

        let type_name = std::any::type_name::<T>();
        #[cfg(feature = "tracing")]
        let _span = info_span!(SPAN_FACTORY_EXECUTE, type_name = type_name).entered();

        let provider_ref = self.resolve_provider::<T>()?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_sync",
            scope = %provider_ref.scope,
            limit_policy = ?provider_ref.limits.policy,
            limit_max = ?provider_ref.limits.max_concurrent_creations,
            "Acquiring factory creation permit"
        );
        let permit = provider_ref.acquire_creation_permit(type_name)?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_sync",
            stage = "permit_acquired",
            "Factory permit acquired"
        );

        #[cfg(feature = "async-factory")]
        if provider_ref.async_factory.is_some() {
            drop(permit);
            #[cfg(feature = "tracing")]
            debug!(
                type_name = type_name,
                op = "factory_execute_sync",
                "Sync resolve attempted on async provider"
            );
            return Err(Error::async_factory_requires_async_resolve(type_name));
        }

        let instance = Shared::new((provider_ref.factory)(self));
        drop(permit);
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_sync",
            scope = %provider_ref.scope,
            "Factory execution completed"
        );
        Ok(instance)
    }

    pub(crate) fn resolve_instance_from_provider<T>(
        &self,
        provider_ref: &Shared<Provider<T>>,
    ) -> Result<Shared<Instance<T>>, Error>
    where
        T: ?Sized + 'static,
    {
        #[cfg(feature = "metrics")]
        self.inner.metrics.record_factory_execution();

        let type_name = std::any::type_name::<T>();
        #[cfg(feature = "tracing")]
        let _span = info_span!(
            SPAN_FACTORY_EXECUTE,
            type_name = type_name,
            op = "resolve_set"
        )
        .entered();

        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_sync_set",
            scope = %provider_ref.scope,
            limit_policy = ?provider_ref.limits.policy,
            limit_max = ?provider_ref.limits.max_concurrent_creations,
            "Acquiring factory creation permit for set binding"
        );
        let permit = provider_ref.acquire_creation_permit(type_name)?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_sync_set",
            stage = "permit_acquired",
            "Factory permit acquired for set binding"
        );

        #[cfg(feature = "async-factory")]
        if provider_ref.async_factory.is_some() {
            drop(permit);
            #[cfg(feature = "tracing")]
            debug!(
                type_name = type_name,
                op = "factory_execute_sync_set",
                "Sync resolve attempted on async provider in set"
            );
            return Err(Error::async_factory_requires_async_resolve(type_name));
        }

        let instance = Shared::new((provider_ref.factory)(self));
        drop(permit);
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_sync_set",
            scope = %provider_ref.scope,
            "Factory execution completed for set binding"
        );
        Ok(instance)
    }

    pub(crate) fn resolve_instance_named<T>(&self, name: &str) -> Result<Shared<Instance<T>>, Error>
    where
        T: ?Sized + 'static,
    {
        #[cfg(feature = "metrics")]
        self.inner.metrics.record_factory_execution();

        let type_name = std::any::type_name::<T>();
        #[cfg(feature = "tracing")]
        let _span = info_span!(SPAN_FACTORY_EXECUTE, type_name = type_name, name = %name).entered();

        let provider_ref = self.resolve_provider_named::<T>(name)?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            name = %name,
            op = "factory_execute_sync_named",
            scope = %provider_ref.scope,
            limit_policy = ?provider_ref.limits.policy,
            limit_max = ?provider_ref.limits.max_concurrent_creations,
            "Acquiring factory creation permit for named binding"
        );
        let permit = provider_ref.acquire_creation_permit(type_name)?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            name = %name,
            op = "factory_execute_sync_named",
            stage = "permit_acquired",
            "Factory permit acquired for named binding"
        );

        #[cfg(feature = "async-factory")]
        if provider_ref.async_factory.is_some() {
            drop(permit);
            #[cfg(feature = "tracing")]
            debug!(
                type_name = type_name,
                name = %name,
                op = "factory_execute_sync_named",
                "Sync resolve attempted on async named provider"
            );
            return Err(Error::async_factory_requires_async_resolve(type_name));
        }

        let instance = Shared::new((provider_ref.factory)(self));
        drop(permit);
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            name = %name,
            op = "factory_execute_sync_named",
            scope = %provider_ref.scope,
            "Factory execution completed for named binding"
        );
        Ok(instance)
    }

    #[cfg(feature = "async-factory")]
    pub(crate) async fn resolve_instance_async<T>(&self) -> Result<Shared<Instance<T>>, Error>
    where
        T: ?Sized + 'static,
    {
        #[cfg(feature = "metrics")]
        self.inner.metrics.record_factory_execution();

        #[cfg(feature = "tracing")]
        let _span =
            info_span!(SPAN_FACTORY_EXECUTE, type_name = std::any::type_name::<T>()).entered();

        let type_name = std::any::type_name::<T>();
        let provider_ref = self.resolve_provider::<T>()?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_async",
            scope = %provider_ref.scope,
            limit_policy = ?provider_ref.limits.policy,
            limit_max = ?provider_ref.limits.max_concurrent_creations,
            "Acquiring async factory creation permit"
        );
        let permit = provider_ref
            .acquire_creation_permit_async(type_name)
            .await?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_async",
            stage = "permit_acquired",
            "Async factory permit acquired"
        );

        if let Some(async_factory) = &provider_ref.async_factory {
            let instance = Shared::new((async_factory)(self.clone()).await);
            drop(permit);
            #[cfg(feature = "tracing")]
            trace!(
                type_name = type_name,
                op = "factory_execute_async",
                scope = %provider_ref.scope,
                mode = "async_factory",
                "Async factory execution completed"
            );
            return Ok(instance);
        }

        let instance = Shared::new((provider_ref.factory)(self));
        drop(permit);
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_async",
            scope = %provider_ref.scope,
            mode = "sync_factory",
            "Sync fallback factory execution completed in async resolve"
        );
        Ok(instance)
    }

    #[cfg(feature = "async-factory")]
    pub(crate) async fn resolve_instance_named_async<T>(
        &self,
        name: &str,
    ) -> Result<Shared<Instance<T>>, Error>
    where
        T: ?Sized + 'static,
    {
        #[cfg(feature = "metrics")]
        self.inner.metrics.record_factory_execution();

        #[cfg(feature = "tracing")]
        let _span =
            info_span!(SPAN_FACTORY_EXECUTE, type_name = std::any::type_name::<T>(), name = %name)
                .entered();

        let type_name = std::any::type_name::<T>();
        let provider_ref = self.resolve_provider_named::<T>(name)?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            name = %name,
            op = "factory_execute_async_named",
            scope = %provider_ref.scope,
            limit_policy = ?provider_ref.limits.policy,
            limit_max = ?provider_ref.limits.max_concurrent_creations,
            "Acquiring async factory creation permit for named binding"
        );
        let permit = provider_ref
            .acquire_creation_permit_async(type_name)
            .await?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            name = %name,
            op = "factory_execute_async_named",
            stage = "permit_acquired",
            "Async factory permit acquired for named binding"
        );

        if let Some(async_factory) = &provider_ref.async_factory {
            let instance = Shared::new((async_factory)(self.clone()).await);
            drop(permit);
            #[cfg(feature = "tracing")]
            trace!(
                type_name = type_name,
                name = %name,
                op = "factory_execute_async_named",
                scope = %provider_ref.scope,
                mode = "async_factory",
                "Async named factory execution completed"
            );
            return Ok(instance);
        }

        let instance = Shared::new((provider_ref.factory)(self));
        drop(permit);
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            name = %name,
            op = "factory_execute_async_named",
            scope = %provider_ref.scope,
            mode = "sync_factory",
            "Sync fallback named factory execution completed in async resolve"
        );
        Ok(instance)
    }

    #[cfg(feature = "async-factory")]
    pub(crate) async fn resolve_instance_from_provider_async<T>(
        &self,
        provider_ref: &Shared<Provider<T>>,
    ) -> Result<Shared<Instance<T>>, Error>
    where
        T: ?Sized + 'static,
    {
        #[cfg(feature = "metrics")]
        self.inner.metrics.record_factory_execution();

        #[cfg(feature = "tracing")]
        let _span = info_span!(
            SPAN_FACTORY_EXECUTE,
            type_name = std::any::type_name::<T>(),
            op = "resolve_set"
        )
        .entered();

        let type_name = std::any::type_name::<T>();
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_async_set",
            scope = %provider_ref.scope,
            limit_policy = ?provider_ref.limits.policy,
            limit_max = ?provider_ref.limits.max_concurrent_creations,
            "Acquiring async factory creation permit for set binding"
        );
        let permit = provider_ref
            .acquire_creation_permit_async(type_name)
            .await?;
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_async_set",
            stage = "permit_acquired",
            "Async factory permit acquired for set binding"
        );

        if let Some(async_factory) = &provider_ref.async_factory {
            let instance = Shared::new((async_factory)(self.clone()).await);
            drop(permit);
            #[cfg(feature = "tracing")]
            trace!(
                type_name = type_name,
                op = "factory_execute_async_set",
                scope = %provider_ref.scope,
                mode = "async_factory",
                "Async set factory execution completed"
            );
            return Ok(instance);
        }

        let instance = Shared::new((provider_ref.factory)(self));
        drop(permit);
        #[cfg(feature = "tracing")]
        trace!(
            type_name = type_name,
            op = "factory_execute_async_set",
            scope = %provider_ref.scope,
            mode = "sync_factory",
            "Sync fallback set factory execution completed in async resolve"
        );
        Ok(instance)
    }
}