use crate::bridge::envelope::{Payload, Response, Status};
use crate::control::gateway::GatewayErrorMap;
use crate::control::gateway::core::QueryContext as GatewayQueryContext;
use crate::control::server::dispatch_utils;
use crate::types::{Lsn, RequestId, TraceId};
use nodedb_physical::physical_task::PhysicalTask;
use super::DispatchCtx;
pub(super) async fn dispatch_task_via_gateway(
ctx: &DispatchCtx<'_>,
task: PhysicalTask,
) -> crate::Result<Response> {
let vshard_id = task.vshard_id;
let tenant_id = task.tenant_id;
let database_id = task.database_id;
let txn_id = task.txn_id;
let plan = task.plan;
match ctx.state.gateway.get() {
Some(gw) => {
let gw_ctx = GatewayQueryContext {
tenant_id,
trace_id: TraceId::generate(),
database_id,
txn_id,
};
gw.execute(&gw_ctx, plan)
.await
.map_err(|e| {
let (code, msg) = GatewayErrorMap::to_native(&e);
crate::Error::Internal {
detail: format!("gateway error {code}: {msg}"),
}
})
.map(payloads_to_response)
}
None => {
dispatch_utils::dispatch_autocommit_write(
ctx.state,
dispatch_utils::AutocommitWrite {
tenant_id,
database_id,
vshard_id,
plan,
trace_id: TraceId::ZERO,
event_source: crate::event::EventSource::User,
txn_id,
},
)
.await
}
}
}
fn payloads_to_response(payloads: Vec<Vec<u8>>) -> Response {
let payload = payloads
.into_iter()
.next()
.map(Payload::from_vec)
.unwrap_or_else(Payload::empty);
Response {
request_id: RequestId::new(0),
status: Status::Ok,
attempt: 0,
partial: false,
payload,
watermark_lsn: Lsn::new(0),
error_code: None,
read_set_valid: None,
read_version_lsn: crate::types::Lsn::ZERO,
write_set: Vec::new(),
}
}