Skip to main content

valence_core/runtime/
factory.rs

1//! Process-global [`ValenceFactory`] from a pinned [`DatabaseRouter`].
2
3use std::sync::Arc;
4
5use serde_json::Value;
6
7use crate::error::Result;
8use crate::ports::actor::{ActorFactory, JsonActorFactory};
9use crate::ports::endpoints::DatabaseEndpointResolver;
10use crate::ports::secrets::SecretProvider;
11use crate::router::DatabaseRouter;
12use crate::runtime::{Valence, ValenceBuilder};
13use valence_telemetry::TelemetrySink;
14
15/// Factory for reconstructing [`Valence`] instances outside request context.
16pub trait ValenceFactory: Send + Sync + 'static {
17    /// Build a request-scoped [`Valence`] from a JSON actor payload.
18    fn build(&self, actor_json: &Value) -> Result<Valence>;
19}
20
21/// Host wiring template applied when building from a shared router.
22#[derive(Clone)]
23pub struct RouterValenceFactoryConfig {
24    /// Active backend key passed to [`ValenceBuilder::default_backend_key`].
25    pub default_backend_key: String,
26    /// Optional telemetry sink override (defaults to no-op).
27    pub telemetry_sink: Option<Arc<dyn TelemetrySink>>,
28    /// Optional secret provider override (defaults to no-op).
29    pub secret_provider: Option<Arc<dyn SecretProvider>>,
30    /// Optional actor factory override (defaults to JSON factory).
31    pub actor_factory: Option<Arc<dyn ActorFactory>>,
32    /// Optional endpoint resolver override (defaults to no-op).
33    pub endpoint_resolver: Option<Arc<dyn DatabaseEndpointResolver>>,
34}
35
36impl RouterValenceFactoryConfig {
37    /// Create a config with only the required default backend key.
38    pub fn new(default_backend_key: impl Into<String>) -> Self {
39        Self {
40            default_backend_key: default_backend_key.into(),
41            telemetry_sink: None,
42            secret_provider: None,
43            actor_factory: None,
44            endpoint_resolver: None,
45        }
46    }
47}
48
49/// [`ValenceFactory`] backed by a shared [`DatabaseRouter`].
50#[derive(Clone)]
51pub struct RouterValenceFactory {
52    router: Arc<DatabaseRouter>,
53    config: RouterValenceFactoryConfig,
54}
55
56impl RouterValenceFactory {
57    /// Wrap a shared router and host wiring template.
58    pub fn new(router: Arc<DatabaseRouter>, config: RouterValenceFactoryConfig) -> Self {
59        Self { router, config }
60    }
61
62    /// Return an [`Arc`] factory suitable for dependency injection.
63    pub fn arc(
64        router: Arc<DatabaseRouter>,
65        config: RouterValenceFactoryConfig,
66    ) -> Arc<dyn ValenceFactory> {
67        Arc::new(Self::new(router, config))
68    }
69}
70
71impl ValenceFactory for RouterValenceFactory {
72    fn build(&self, actor_json: &Value) -> Result<Valence> {
73        let actor_factory = self
74            .config
75            .actor_factory
76            .clone()
77            .unwrap_or_else(|| Arc::new(JsonActorFactory));
78        let _actor_ctx = actor_factory.build(actor_json)?;
79
80        let mut builder = ValenceBuilder::new()
81            .database_router(Arc::clone(&self.router))
82            .default_backend_key(self.config.default_backend_key.clone())
83            .actor_factory(actor_factory);
84
85        if let Some(sink) = &self.config.telemetry_sink {
86            builder = builder.telemetry_sink(Arc::clone(sink));
87        }
88        if let Some(secrets) = &self.config.secret_provider {
89            builder = builder.secret_provider(Arc::clone(secrets));
90        }
91        if let Some(endpoints) = &self.config.endpoint_resolver {
92            builder = builder.endpoint_resolver(Arc::clone(endpoints));
93        }
94
95        builder.build()
96    }
97}