use crate::backend::{BackendCapability, BackendCapabilityMatrixEntry, BackendKind};
use crate::runtime::config::{BackendInstanceConfig, UdbConfig};
use crate::runtime::core::{DataBrokerRuntime, RuntimeInitReport};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BackendSupportState {
Unknown,
KnownUnsupported,
DisabledByFeature,
RuntimeSupported,
}
impl BackendSupportState {
pub fn as_str(self) -> &'static str {
match self {
Self::Unknown => "unknown",
Self::KnownUnsupported => "known_unsupported",
Self::DisabledByFeature => "disabled_by_feature",
Self::RuntimeSupported => "runtime_supported",
}
}
pub fn is_runtime_supported(self) -> bool {
matches!(self, Self::RuntimeSupported)
}
pub fn diagnostic(self, backend: &str) -> String {
match self {
Self::Unknown => format!("backend '{backend}' is not known to UDB"),
Self::KnownUnsupported => format!(
"backend '{backend}' is known to UDB metadata but has no runtime executor in this version"
),
Self::DisabledByFeature => format!(
"backend '{backend}' is not available in this binary; rebuild with the matching Cargo feature"
),
Self::RuntimeSupported => format!("backend '{backend}' is runtime-supported"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BackendPluginSurface {
pub name: String,
pub description: String,
pub required: bool,
}
impl BackendPluginSurface {
pub fn required(name: &str, description: &str) -> Self {
Self {
name: name.to_string(),
description: description.to_string(),
required: true,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BackendPluginContract {
pub backend: String,
pub tier: String,
pub config_schema: BackendPluginSurface,
pub connection_factory: BackendPluginSurface,
pub logical_ir_compiler: BackendPluginSurface,
pub executor: BackendPluginSurface,
pub migration_resource_applier: BackendPluginSurface,
pub health_probe: BackendPluginSurface,
pub metrics_labels: Vec<String>,
pub capability_matrix: BackendCapabilityMatrixEntry,
}
impl BackendPluginContract {
pub fn default_for(kind: BackendKind) -> Self {
Self {
backend: kind.as_str().to_string(),
tier: kind.tier().as_str().to_string(),
config_schema: BackendPluginSurface::required(
"BackendInstanceConfig",
"Declarative config schema for DSN, labels, pool limits, routing, and feature gates",
),
connection_factory: BackendPluginSurface::required(
"Backend::register",
"Startup-time connection/client factory owned by the plugin",
),
logical_ir_compiler: BackendPluginSurface::required(
"ir::compile",
"Compiler from neutral logical operations into backend wire requests",
),
executor: BackendPluginSurface::required(
"runtime::executors::DispatchFactory",
"Runtime executor for generic query/mutate/search/object/resource operations",
),
migration_resource_applier: BackendPluginSurface::required(
"Backend::generate_artifacts",
"Migration/resource artifact generator and applier ownership point",
),
health_probe: BackendPluginSurface::required(
"probe",
"Backend-specific health probe used by startup, reload, and admin APIs",
),
metrics_labels: vec![
"project".to_string(),
"backend".to_string(),
"tier".to_string(),
"instance".to_string(),
"operation".to_string(),
],
capability_matrix: kind.capability_matrix_entry(),
}
}
pub fn conformance_report(&self) -> BackendConformanceReport {
let mut failures = Vec::new();
let required_surfaces = [
&self.config_schema,
&self.connection_factory,
&self.logical_ir_compiler,
&self.executor,
&self.migration_resource_applier,
&self.health_probe,
];
for surface in required_surfaces {
if surface.required
&& (surface.name.trim().is_empty() || surface.description.trim().is_empty())
{
failures.push(format!("required surface '{}' is incomplete", surface.name));
}
}
for label in ["backend", "tier", "instance", "operation"] {
if !self.metrics_labels.iter().any(|item| item == label) {
failures.push(format!("missing required metrics label '{label}'"));
}
}
if self.capability_matrix.backend != self.backend {
failures.push("capability matrix backend does not match contract backend".to_string());
}
if self.capability_matrix.tier != self.tier {
failures.push("capability matrix tier does not match contract tier".to_string());
}
if self.capability_matrix.operations.is_empty() {
failures.push("capability matrix must declare at least one operation".to_string());
}
let kind = BackendKind::from_token(&self.backend);
let (
native_executor,
compiler_mediated,
lifecycle,
system_store,
canonical_candidate,
canonical_goal,
) = match kind {
Some(k) => {
let v2 = k.capabilities_v2();
(
v2.native_executor,
compiler_mediated_runtime_path_wired(&k),
v2.lifecycle.as_str().to_string(),
v2.system_store.as_str().to_string(),
v2.canonical_candidate.as_str().to_string(),
v2.canonical_goal.to_string(),
)
}
None => {
failures.push(format!(
"contract backend '{}' does not resolve to a BackendKind",
self.backend
));
(
false,
false,
"unknown".to_string(),
"unknown".to_string(),
"unknown".to_string(),
String::new(),
)
}
};
BackendConformanceReport {
backend: self.backend.clone(),
passed: failures.is_empty(),
failures,
native_executor,
compiler_mediated,
lifecycle,
system_store,
canonical_candidate,
canonical_goal,
}
}
}
pub(crate) fn compiler_mediated_runtime_path_wired(kind: &BackendKind) -> bool {
if !kind.capabilities_v2().compiler_mediated {
return false;
}
crate::ir::compile::is_mediated_backend(kind)
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BackendConformanceReport {
pub backend: String,
pub passed: bool,
pub failures: Vec<String>,
#[serde(default)]
pub native_executor: bool,
#[serde(default)]
pub compiler_mediated: bool,
#[serde(default)]
pub lifecycle: String,
#[serde(default)]
pub system_store: String,
#[serde(default)]
pub canonical_candidate: String,
#[serde(default)]
pub canonical_goal: String,
}
pub fn has_runtime_implementation(kind: &BackendKind) -> bool {
matches!(
kind,
BackendKind::Postgres
| BackendKind::Mysql
| BackendKind::Sqlite
| BackendKind::Redis
| BackendKind::Qdrant
| BackendKind::Minio
| BackendKind::S3
| BackendKind::Mongodb
| BackendKind::Neo4j
| BackendKind::Clickhouse
| BackendKind::Mssql
| BackendKind::Memcached
| BackendKind::Elasticsearch
| BackendKind::Weaviate
| BackendKind::Pinecone
| BackendKind::Cassandra
| BackendKind::AzureBlob
| BackendKind::Gcs
)
}
pub fn support_state_for_kind(kind: &BackendKind) -> BackendSupportState {
if all_plugins()
.into_iter()
.any(|plugin| plugin.kind() == *kind)
{
BackendSupportState::RuntimeSupported
} else if has_runtime_implementation(kind) {
BackendSupportState::DisabledByFeature
} else {
BackendSupportState::KnownUnsupported
}
}
pub fn support_state_for_token(token: &str) -> BackendSupportState {
let Some(kind) =
BackendKind::from_store_kind("", token).or_else(|| BackendKind::from_token(token))
else {
return BackendSupportState::Unknown;
};
support_state_for_kind(&kind)
}
pub struct RegisterCtx<'a> {
pub config: &'a UdbConfig,
pub instance_config: &'a BackendInstanceConfig,
pub app_name: &'a str,
pub runtime: &'a mut DataBrokerRuntime,
pub report: &'a mut RuntimeInitReport,
}
#[async_trait::async_trait]
pub trait Backend: Send + Sync {
fn kind(&self) -> BackendKind;
fn enabled(&self) -> bool {
true
}
fn capabilities(&self) -> BackendCapability {
self.kind().capabilities()
}
fn dsn_scheme(&self) -> String {
self.kind().dsn_scheme()
}
fn default_dsn_env(&self) -> &'static str {
self.kind().default_env_key()
}
fn contract(&self) -> BackendPluginContract {
BackendPluginContract::default_for(self.kind())
}
fn conformance_report(&self) -> BackendConformanceReport {
self.contract().conformance_report()
}
async fn register(&self, _ctx: &mut RegisterCtx<'_>) {}
fn generate_artifacts(
&self,
_manifest: &crate::generation::CatalogManifest,
_sql_config: &crate::generation::sql::SqlGenerationConfig,
) -> Result<Vec<crate::generation::GeneratedArtifact>, String> {
Ok(Vec::new())
}
fn sync_subdir(&self) -> &'static str {
self.kind().as_str()
}
}
pub fn all_plugins() -> Vec<&'static dyn Backend> {
crate::backend::plugins::all()
}
pub fn plugin_for(token: &str) -> Option<&'static dyn Backend> {
let kind = BackendKind::from_token(token)?;
all_plugins().into_iter().find(|p| p.kind() == kind)
}
pub fn plugin_for_kind(kind: &BackendKind) -> Option<&'static dyn Backend> {
all_plugins().into_iter().find(|p| p.kind() == *kind)
}
#[cfg(test)]
mod tests {
use super::*;
fn expected_runtime_plugin_kinds() -> Vec<BackendKind> {
vec![
BackendKind::Postgres,
#[cfg(feature = "mysql")]
BackendKind::Mysql,
#[cfg(feature = "sqlite")]
BackendKind::Sqlite,
#[cfg(feature = "redis")]
BackendKind::Redis,
#[cfg(feature = "qdrant")]
BackendKind::Qdrant,
#[cfg(feature = "s3")]
BackendKind::Minio,
#[cfg(feature = "s3")]
BackendKind::S3,
#[cfg(feature = "mongodb")]
BackendKind::Mongodb,
#[cfg(feature = "neo4j")]
BackendKind::Neo4j,
#[cfg(feature = "clickhouse")]
BackendKind::Clickhouse,
#[cfg(feature = "elasticsearch")]
BackendKind::Elasticsearch,
#[cfg(feature = "memcached")]
BackendKind::Memcached,
#[cfg(feature = "mssql")]
BackendKind::Mssql,
#[cfg(feature = "weaviate")]
BackendKind::Weaviate,
#[cfg(feature = "pinecone")]
BackendKind::Pinecone,
#[cfg(feature = "cassandra")]
BackendKind::Cassandra,
#[cfg(feature = "azureblob")]
BackendKind::AzureBlob,
#[cfg(feature = "gcs")]
BackendKind::Gcs,
]
}
#[test]
fn wired_classification_agrees_with_single_source_of_truth() {
for kind in BackendKind::all_known() {
let expected = kind.capabilities_v2().compiler_mediated
&& crate::ir::compile::is_mediated_backend(kind);
assert_eq!(
compiler_mediated_runtime_path_wired(kind),
expected,
"{kind:?}: wired classification diverged from V2 filter + is_mediated_backend"
);
}
}
#[test]
fn registry_is_non_empty_and_contains_postgres() {
let plugins = all_plugins();
assert!(!plugins.is_empty(), "registry must not be empty");
assert!(
plugins.iter().any(|p| p.kind() == BackendKind::Postgres),
"postgres plugin must always be registered"
);
}
#[test]
fn registry_matches_compiled_runtime_backends() {
let actual: Vec<_> = all_plugins().into_iter().map(|p| p.kind()).collect();
assert_eq!(actual, expected_runtime_plugin_kinds());
}
#[test]
fn plugin_metadata_matches_backend_kind() {
for plugin in all_plugins() {
let kind = plugin.kind();
assert_eq!(plugin.dsn_scheme(), kind.dsn_scheme(), "{kind:?}");
assert_eq!(plugin.default_dsn_env(), kind.default_env_key(), "{kind:?}");
assert_eq!(plugin.capabilities(), kind.capabilities(), "{kind:?}");
assert_eq!(plugin.contract().backend, kind.as_str(), "{kind:?}");
}
}
#[test]
fn registered_plugins_satisfy_stable_contract() {
for plugin in all_plugins() {
let report = plugin.conformance_report();
assert!(
report.passed,
"{} plugin contract failed: {:?}",
report.backend, report.failures
);
}
}
struct ToyBackend;
#[async_trait::async_trait]
impl Backend for ToyBackend {
fn kind(&self) -> BackendKind {
BackendKind::Sqlite
}
}
#[test]
fn toy_backend_can_conform_without_runtime_core_edits() {
let plugin = ToyBackend;
let contract = plugin.contract();
assert_eq!(contract.backend, "sqlite");
assert!(plugin.conformance_report().passed);
assert!(
contract
.capability_matrix
.operations
.contains(&"ping".to_string())
);
}
#[test]
fn plugin_for_round_trips_through_canonical_token() {
for plugin in all_plugins() {
let token = plugin.kind().as_str();
let resolved = plugin_for(token).unwrap_or_else(|| {
panic!("plugin_for({token}) returned None for registered plugin")
});
assert_eq!(resolved.kind(), plugin.kind());
}
assert!(plugin_for("not_a_backend").is_none());
}
#[test]
fn support_state_distinguishes_metadata_from_runtime() {
assert_eq!(
support_state_for_kind(&BackendKind::Postgres),
BackendSupportState::RuntimeSupported
);
#[cfg(feature = "mysql")]
assert_eq!(
support_state_for_kind(&BackendKind::Mysql),
BackendSupportState::RuntimeSupported
);
#[cfg(feature = "sqlite")]
assert_eq!(
support_state_for_kind(&BackendKind::Sqlite),
BackendSupportState::RuntimeSupported
);
#[cfg(feature = "mssql")]
assert_eq!(
support_state_for_kind(&BackendKind::Mssql),
BackendSupportState::RuntimeSupported
);
#[cfg(feature = "cassandra")]
assert_eq!(
support_state_for_kind(&BackendKind::Cassandra),
BackendSupportState::RuntimeSupported
);
assert_eq!(
support_state_for_token("not_a_backend"),
BackendSupportState::Unknown
);
assert!(support_state_for_token("postgres").is_runtime_supported());
}
#[test]
fn every_plugin_kind_matches_its_contract() {
for plugin in all_plugins() {
let kind = plugin.kind();
let contract = plugin.contract();
assert_eq!(
contract.backend,
kind.as_str(),
"{kind:?}: contract backend token mismatch"
);
assert_eq!(
contract.tier,
kind.tier().as_str(),
"{kind:?}: contract tier mismatch"
);
assert_eq!(
contract.capability_matrix.backend,
kind.as_str(),
"{kind:?}: contract capability_matrix backend mismatch"
);
}
}
#[test]
fn runtime_plugins_advertising_dispatch_ops_have_a_dispatch_factory() {
use crate::runtime::executors::handle::dispatch_factory_for;
for plugin in all_plugins() {
let kind = plugin.kind();
let ops = kind.supported_operations();
let advertises_real_ops = ops.iter().any(|op| *op != "ping" && *op != "probe");
if advertises_real_ops {
assert!(
dispatch_factory_for(&kind).is_some(),
"{kind:?} advertises dispatch ops {ops:?} but has no DispatchFactory"
);
}
}
}
#[test]
fn conformance_report_carries_capability_evidence() {
for plugin in all_plugins() {
let kind = plugin.kind();
let report = plugin.conformance_report();
assert!(
report.passed,
"{kind:?} conformance failed: {:?}",
report.failures
);
let v2 = kind.capabilities_v2();
assert_eq!(report.native_executor, v2.native_executor, "{kind:?}");
assert_eq!(
report.compiler_mediated,
compiler_mediated_runtime_path_wired(&kind),
"{kind:?}"
);
assert!(
!report.compiler_mediated || v2.compiler_mediated,
"{kind:?} cannot report compiler mediation without a static compiler"
);
assert_eq!(report.lifecycle, v2.lifecycle.as_str(), "{kind:?}");
assert_eq!(report.system_store, v2.system_store.as_str(), "{kind:?}");
assert_eq!(
report.canonical_candidate,
v2.canonical_candidate.as_str(),
"{kind:?}"
);
assert_eq!(report.canonical_goal, v2.canonical_goal, "{kind:?}");
assert!(
report.native_executor,
"{kind:?} is a registered plugin but reports no native executor"
);
}
}
#[test]
fn conformance_report_marks_wired_neutral_ir_dispatch_as_compiler_mediated() {
for backend in [BackendKind::Mongodb, BackendKind::Clickhouse] {
if let Some(plugin) = plugin_for_kind(&backend) {
let report = plugin.conformance_report();
assert!(
report.compiler_mediated,
"{backend:?} generic dispatch accepts neutral IR, compiles it, and executes the compiled rendering"
);
}
}
}
#[test]
fn known_but_compiled_out_backends_classify_as_disabled_by_feature() {
let live: Vec<BackendKind> = all_plugins().into_iter().map(|p| p.kind()).collect();
for kind in BackendKind::all_known() {
if live.contains(kind) {
assert_eq!(
support_state_for_kind(kind),
BackendSupportState::RuntimeSupported,
"{kind:?} is in the live registry"
);
} else {
assert_eq!(
support_state_for_kind(kind),
BackendSupportState::DisabledByFeature,
"{kind:?} is compiled out and must report DisabledByFeature, not \
KnownUnsupported"
);
assert!(
has_runtime_implementation(kind),
"{kind:?} must have a runtime implementation to be DisabledByFeature"
);
}
}
}
}