Skip to main content

valence_core/
evaluator.rs

1//! Runtime resolution of which [`crate::backend::DatabaseBackend`] a schema uses.
2//!
3//! Schema `database:` fields point at a [`DatabaseEvaluator`] (usually [`DatabaseFromEngine`]).
4//! That is **router-key** selection — not physical URL resolution
5//! ([`crate::DatabaseEndpointResolver`] is bootstrap-only).
6
7use crate::backend::DatabaseBackend;
8use crate::error::Result;
9use crate::router::DatabaseRouter;
10use crate::router_key::router_key;
11use async_trait::async_trait;
12use std::any::Any;
13use std::sync::Arc;
14
15#[derive(Debug, Clone, Default)]
16pub struct ResolverContext {
17    pub environment: Option<String>,
18}
19
20#[async_trait]
21pub trait DatabaseEvaluator: Send + Sync + std::fmt::Debug + Any + 'static {
22    /// Logical database name used in schema metadata (`databases:` labels).
23    fn logical_name(&self) -> &'static str;
24
25    /// Alias for [`Self::logical_name`] — used by `valence_schema!` codegen.
26    fn name(&self) -> &'static str {
27        self.logical_name()
28    }
29
30    fn engine_id(&self) -> &'static str;
31    async fn resolve(
32        &self,
33        ctx: &ResolverContext,
34        router: &DatabaseRouter,
35    ) -> Result<Arc<dyn DatabaseBackend>>;
36    fn as_any(&self) -> &dyn Any;
37}
38
39/// Built-in evaluator: look up `logical_name` + `engine_id` on a [`DatabaseRouter`].
40///
41/// Composes [`crate::router_key()`] then [`DatabaseRouter::resolve`].
42///
43/// # Examples
44///
45/// ```
46/// use valence_backend_mem::ENGINE_ID;
47/// use valence_core::{Database, DatabaseEvaluator};
48///
49/// let db = Database::from_engine("default", ENGINE_ID);
50/// assert_eq!(db.logical_name(), "default");
51/// assert_eq!(db.engine_id(), ENGINE_ID);
52/// ```
53#[derive(Debug, Clone, Copy)]
54pub struct DatabaseFromEngine {
55    logical_name: &'static str,
56    engine_id: &'static str,
57}
58
59impl DatabaseFromEngine {
60    pub const fn new(logical_name: &'static str, engine_id: &'static str) -> Self {
61        Self {
62            logical_name,
63            engine_id,
64        }
65    }
66}
67
68#[async_trait]
69impl DatabaseEvaluator for DatabaseFromEngine {
70    fn logical_name(&self) -> &'static str {
71        self.logical_name
72    }
73
74    fn engine_id(&self) -> &'static str {
75        self.engine_id
76    }
77
78    async fn resolve(
79        &self,
80        _ctx: &ResolverContext,
81        router: &DatabaseRouter,
82    ) -> Result<Arc<dyn DatabaseBackend>> {
83        let key = router_key(self.logical_name, self.engine_id);
84        router.resolve(&key)
85    }
86
87    fn as_any(&self) -> &dyn Any {
88        self
89    }
90}
91
92/// Convenience namespace for built-in evaluators.
93pub struct Database;
94
95impl Database {
96    pub const fn from_engine(
97        logical_name: &'static str,
98        engine_id: &'static str,
99    ) -> DatabaseFromEngine {
100        DatabaseFromEngine::new(logical_name, engine_id)
101    }
102}
103
104use crate::known_engines::KnownEngines;
105
106pub const DEFAULT_IN_MEMORY: DatabaseFromEngine =
107    DatabaseFromEngine::new("default", KnownEngines::INMEMORY_MEM);
108
109pub use crate::router_key::DEFAULT_IN_MEMORY_ROUTER_KEY;