futu_backend/
connection_lifecycle_runtime.rs1use async_trait::async_trait;
9use bytes::Bytes;
10use futu_command_runtime::{
11 CommandExecutionContext, CommandRequest, CommandResponse, CommandTransport,
12 ConnectionLifecycleRuntime,
13};
14use futu_command_spec::{BackendChannelKind, CommandSpecId, command_spec_by_id};
15use futu_core::error::{FutuError, Result};
16
17use crate::conn::BackendConn;
18
19struct ConnectionLifecycleBackendTransport<'a> {
20 conn: &'a BackendConn,
21 channel: BackendChannelKind,
22}
23
24#[async_trait]
25impl CommandTransport for ConnectionLifecycleBackendTransport<'_> {
26 fn channel_kind(&self) -> Option<BackendChannelKind> {
27 Some(self.channel)
28 }
29
30 async fn execute(&self, request: CommandRequest) -> Result<CommandResponse> {
31 let frame = self
32 .conn
33 .request_with_reserved(request.cmd_id, request.body.to_vec(), request.reserved)
34 .await?;
35 Ok(CommandResponse {
36 request_serial_no: frame.header.serial_no,
37 cmd_id: frame.header.cmd_id,
38 body: frame.body,
39 ex_head: frame.ex_head,
40 })
41 }
42}
43
44pub async fn execute_connection_lifecycle(
45 conn: &BackendConn,
46 spec_id: CommandSpecId,
47 body: Vec<u8>,
48) -> Result<CommandResponse> {
49 let spec = command_spec_by_id(spec_id)
50 .ok_or_else(|| FutuError::Codec(format!("unknown lifecycle command spec: {spec_id:?}")))?;
51 let runtime = ConnectionLifecycleRuntime::new(ConnectionLifecycleBackendTransport {
52 conn,
53 channel: spec.channel,
54 });
55 let execution = runtime
56 .execute(CommandExecutionContext::new(spec_id, Bytes::from(body)))
57 .await
58 .map_err(|error| FutuError::Codec(format!("connection lifecycle spec error: {error}")))?;
59 let report = &execution.report;
60 tracing::trace!(
61 command = report.command_name,
62 cmd_id = report.cmd_id,
63 channel = ?report.channel,
64 outcome = ?report.outcome,
65 response_body_len = report.response_body_len,
66 "connection lifecycle runtime executed transport primitive"
67 );
68 execution.into_response()
69}