Skip to main content

reifydb_sub_server/
binding.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4//! Dispatch bridge for Binding-driven calls.
5//!
6//! Synthesizes a `CALL ns::proc()` statement from a `Binding` + caller-supplied `Params`
7//! and routes it through the shared `dispatch::dispatch` pipeline. All three transport
8//! crates (HTTP, gRPC, WS) call this helper and wrap the returned `(Vec<Frame>, ExecutionMetrics)`
9//! in their own response envelope.
10
11#[cfg(not(reifydb_single_threaded))]
12use std::fmt::Write;
13
14#[cfg(not(reifydb_single_threaded))]
15use reifydb_core::{actors::server::Operation, metric::ExecutionMetrics};
16#[cfg(not(reifydb_single_threaded))]
17use reifydb_type::{
18	params::Params,
19	value::{frame::frame::Frame, identity::IdentityId},
20};
21
22#[cfg(not(reifydb_single_threaded))]
23use crate::{
24	dispatch::dispatch,
25	execute::ExecuteError,
26	interceptor::{RequestContext, RequestMetadata},
27	state::AppState,
28};
29
30/// Synthesize and dispatch `CALL {ns}::{proc}()` for a binding; parameters are resolved
31/// at execution time from `params` (no `$name` placeholders in the CALL text).
32///
33/// The caller is responsible for:
34/// - Resolving the binding and locating its procedure by `binding.procedure_id`.
35/// - Validating `params` against the procedure's declared parameter list (rejecting unknown keys, missing required,
36///   type-coercion failures) before calling here.
37/// - Building `RequestMetadata` from its transport-specific request.
38///
39/// Returns `(frames, metrics)` from the engine; each transport wraps it into its own
40/// response format based on `binding.format` and reads `metrics.total` / `metrics.fingerprint`
41/// for telemetry headers.
42#[cfg(not(reifydb_single_threaded))]
43pub async fn dispatch_binding(
44	state: &AppState,
45	namespace_path: &str,
46	procedure_name: &str,
47	params: Params,
48	identity: IdentityId,
49	metadata: RequestMetadata,
50) -> Result<(Vec<Frame>, ExecutionMetrics), ExecuteError> {
51	let mut call_text = String::with_capacity(8 + namespace_path.len() + procedure_name.len());
52	write!(&mut call_text, "CALL {}::{}()", namespace_path, procedure_name).unwrap();
53
54	let ctx = RequestContext {
55		identity,
56		operation: Operation::Command,
57		rql: call_text,
58		params,
59		metadata,
60	};
61
62	dispatch(state, ctx).await
63}