fraiseql_server/tenancy/mod.rs
1//! Multi-tenancy infrastructure: pool factory, executor construction, health monitoring.
2
3pub mod pool_factory;
4
5use std::{future::Future, pin::Pin, sync::Arc};
6
7use fraiseql_core::runtime::Executor;
8use fraiseql_error::Result;
9pub use pool_factory::{FromPoolConfig, TenantPoolConfig, create_tenant_executor};
10
11/// Type-erased async factory for creating tenant executors.
12///
13/// Stored in `AppState` so that the management API handler (`upsert_tenant_handler`)
14/// can build an `Executor<A>` without requiring `A: FromPoolConfig` as a bound on
15/// the route handler or the `Server<A>` impl. The factory is set once at server
16/// startup by code that knows the concrete adapter type.
17pub type TenantExecutorFactory<A> = Arc<
18 dyn Fn(
19 String,
20 TenantPoolConfig,
21 ) -> Pin<Box<dyn Future<Output = Result<Arc<Executor<A>>>> + Send>>
22 + Send
23 + Sync,
24>;
25
26/// Create a `TenantExecutorFactory` for an adapter that implements `FromPoolConfig`.
27///
28/// Captures the `FromPoolConfig` bound at construction time so that the factory
29/// can be stored as a type-erased closure in `AppState`.
30pub fn make_executor_factory<A: FromPoolConfig + 'static>() -> TenantExecutorFactory<A> {
31 Arc::new(|schema_json, pool_config| {
32 Box::pin(async move { create_tenant_executor::<A>(&schema_json, &pool_config).await })
33 })
34}