dtmrs_server/grpc/
server.rs1use tonic::{Request, Response, Status};
9
10use super::pb;
11use crate::api::{Api, ApiError, RegisterBranch};
12use dtmrs_core::SagaStep;
13
14impl From<ApiError> for Status {
15 fn from(e: ApiError) -> Self {
16 match &e {
17 ApiError::BadRequest(m) => Status::invalid_argument(m.clone()),
18 ApiError::NotFound(m) => Status::not_found(m.clone()),
19 ApiError::Conflict(m) => Status::failed_precondition(m.clone()),
20 ApiError::Internal(m) => Status::internal(m.clone()),
21 }
22 }
23}
24
25pub struct TcService {
26 api: Api,
27}
28
29impl TcService {
30 pub fn new(api: Api) -> Self {
31 Self { api }
32 }
33
34 pub fn into_server(self) -> pb::tc_server::TcServer<Self> {
36 pb::tc_server::TcServer::new(self)
37 }
38
39 pub fn into_server_with_auth(
46 self,
47 auth: std::sync::Arc<crate::auth::Auth>,
48 ) -> tonic::service::interceptor::InterceptedService<
49 pb::tc_server::TcServer<Self>,
50 impl tonic::service::Interceptor + Clone,
51 > {
52 pb::tc_server::TcServer::with_interceptor(self, move |req: tonic::Request<()>| {
53 let ok = req
54 .metadata()
55 .get("authorization")
56 .and_then(|v| v.to_str().ok())
57 .and_then(crate::auth::Auth::bearer)
58 .is_some_and(|t| auth.token_ok(t));
59 if ok {
60 Ok(req)
61 } else {
62 Err(tonic::Status::unauthenticated("需要 Bearer token"))
63 }
64 })
65 }
66}
67
68#[tonic::async_trait]
69impl pb::tc_server::Tc for TcService {
70 async fn new_gid(
71 &self,
72 _req: Request<pb::NewGidRequest>,
73 ) -> Result<Response<pb::NewGidReply>, Status> {
74 Ok(Response::new(pb::NewGidReply {
75 gid: self.api.new_gid(),
76 }))
77 }
78
79 async fn prepare(
80 &self,
81 req: Request<pb::PrepareRequest>,
82 ) -> Result<Response<pb::Empty>, Status> {
83 let r = req.into_inner();
84 let grace = if r.grace_secs > 0 {
87 Some(r.grace_secs)
88 } else {
89 None
90 };
91 self.api
92 .prepare(&r.gid, &r.trans_type, &r.actions, &r.query_prepared, grace)
93 .await?;
94 Ok(Response::new(pb::Empty {}))
95 }
96
97 async fn register_branch(
98 &self,
99 req: Request<pb::RegisterBranchRequest>,
100 ) -> Result<Response<pb::Empty>, Status> {
101 let r = req.into_inner();
102 self.api
103 .register_branch(&RegisterBranch {
104 gid: r.gid,
105 branch_id: r.branch_id,
106 confirm: r.confirm,
107 cancel: r.cancel,
108 r#try: r.r#try,
109 commit: r.commit,
110 rollback: r.rollback,
111 })
112 .await?;
113 Ok(Response::new(pb::Empty {}))
114 }
115
116 async fn submit(&self, req: Request<pb::SubmitRequest>) -> Result<Response<pb::Empty>, Status> {
117 let r = req.into_inner();
118 let tt = if r.trans_type.is_empty() {
119 "saga"
120 } else {
121 &r.trans_type
122 };
123 let steps: Vec<SagaStep> = r
124 .steps
125 .into_iter()
126 .map(|s| SagaStep {
127 action: s.action,
128 compensate: s.compensate,
129 payload: s.payload,
130 })
131 .collect();
132 self.api.submit(&r.gid, tt, &steps).await?;
133 Ok(Response::new(pb::Empty {}))
134 }
135
136 async fn abort(&self, req: Request<pb::AbortRequest>) -> Result<Response<pb::Empty>, Status> {
137 self.api.abort(&req.into_inner().gid).await?;
138 Ok(Response::new(pb::Empty {}))
139 }
140
141 async fn retry(&self, req: Request<pb::RetryRequest>) -> Result<Response<pb::Empty>, Status> {
142 self.api.retry(&req.into_inner().gid).await?;
143 Ok(Response::new(pb::Empty {}))
144 }
145
146 async fn query(
147 &self,
148 req: Request<pb::QueryRequest>,
149 ) -> Result<Response<pb::TransView>, Status> {
150 let v = self.api.query(&req.into_inner().gid).await?;
151 Ok(Response::new(pb::TransView {
152 gid: v.gid,
153 trans_type: v.trans_type,
154 status: v.status,
155 rollback_reason: v.rollback_reason,
156 create_time: v.create_time,
157 finish_time: v.finish_time,
158 branches: v
159 .branches
160 .into_iter()
161 .map(|b| pb::BranchView {
162 branch_id: b.branch_id,
163 op: b.op,
164 url: b.url,
165 status: b.status,
166 })
167 .collect(),
168 }))
169 }
170}