Skip to main content

udb/backend/plugins/
postgres.rs

1//! Postgres plugin.
2//!
3//! Identity comes from the trait defaults (delegated to `BackendKind`).
4//! Runtime registration delegates to `runtime::core::setup_data::register_postgres`,
5//! which lives in `runtime/core/` so it can reach `DataBrokerRuntime`'s private
6//! pool/instance fields (§9.5).
7
8use crate::backend::BackendKind;
9use crate::backend::plugin::{Backend, RegisterCtx};
10
11/// Zero-sized plugin for PostgreSQL.
12#[derive(Debug, Default)]
13pub struct PostgresPlugin;
14
15/// Static instance referenced by `backend::plugins::all()`.
16pub static PLUGIN: PostgresPlugin = PostgresPlugin;
17
18#[async_trait::async_trait]
19impl Backend for PostgresPlugin {
20    fn kind(&self) -> BackendKind {
21        BackendKind::Postgres
22    }
23
24    async fn register(&self, ctx: &mut RegisterCtx<'_>) {
25        crate::runtime::core::setup_data::register_postgres(ctx).await;
26    }
27}
28
29impl crate::runtime::executors::handle::DispatchFactory for PostgresPlugin {
30    fn build_dispatch_executor(
31        &self,
32        runtime: &crate::runtime::core::DataBrokerRuntime,
33        instance: Option<&str>,
34        _write: bool,
35        context: Option<&crate::broker::RequestContext>,
36    ) -> Result<crate::runtime::executors::handle::DispatchExecutor, tonic::Status> {
37        // Postgres generic-dispatch resolves the pool from `instance` directly;
38        // replica/cache/encryption for the typed RPCs live elsewhere (§9.1).
39        // U7: when a request context is present, bake it into the executor so
40        // `query`/`mutate` wrap the SQL in a transaction with
41        // `set_request_local_settings` applied — RLS now sees the same
42        // tenant/project/purpose values on the generic-dispatch path that the
43        // typed Select/Upsert RPCs install.
44        let pool = runtime.pg_pool_for_instance(instance)?.clone();
45        let executor = match context {
46            Some(ctx) => crate::runtime::executors::postgres::PostgresExecutor::with_context(
47                pool,
48                std::sync::Arc::new(ctx.clone()),
49            ),
50            None => crate::runtime::executors::postgres::PostgresExecutor::with_pool(pool),
51        };
52        Ok(crate::runtime::executors::handle::DispatchExecutor::Postgres(executor))
53    }
54}