buntrail_engine/remote/
operations.rs1use super::*;
2pub(super) fn uncertain(id: OperationID, target: TargetIdentity, e: CoreError) -> OperationReceipt {
3 OperationReceipt {
5 id,
6 state: OperationState::Unknown(ReconciliationEvidence {
7 target,
8 observed: ObservedState::Unobserved,
9 explanation: format!(
10 "{}; inspect the original operation; automatic replay is disabled",
11 e.message
12 ),
13 }),
14 }
15}
16impl OperationService for RemoteServices {
17 fn inspect(
18 &self,
19 id: OperationID,
20 target: TargetIdentity,
21 ) -> ServiceFuture<'_, Result<OperationReceipt, CoreError>> {
22 Box::pin(async move {
23 self.check(&target)?;
24 match self.call(w::Call::Inspect, Some(id))? {
25 w::Reply::Receipt { receipt } => {
26 let r = receipt.core(&target)?;
27 if r.id != id {
28 return Err(w::invalid());
29 }
30 Ok(r)
31 }
32 _ => Err(w::invalid()),
33 }
34 })
35 }
36}
37
38impl RemoteServices {
39 pub(super) fn mutation_call(
40 &self,
41 call: w::Call,
42 id: OperationID,
43 target: &TargetIdentity,
44 ) -> OperationReceipt {
45 let lookup_sensitive = call.unprepared_worktree_mutation();
46 let mut replies = match self.stream(call, Some(id)) {
47 Ok(stream) => stream,
48 Err(error) if lookup_sensitive => return uncertain(id, target.clone(), error),
49 Err(error) => return buntrail_services::files::failure(id, target.clone(), error),
50 };
51 let result = (|| {
52 loop {
53 let frame = self.next_reply(&mut replies.request)?;
54 if matches!(frame.header.message, Message::Receipt { .. }) {
56 let receipt = super::files::legacy_receipt(id, target, frame.header.message)?;
57 replies.request.finish();
58 return Ok(receipt);
59 }
60 if let Some(value) = replies.accept(frame)? {
61 let w::Reply::Receipt { receipt } = value? else {
62 return Err(w::invalid());
63 };
64 let receipt = receipt.core(target)?;
65 if receipt.id != id {
66 return Err(w::invalid());
67 }
68 return Ok(receipt);
69 }
70 }
71 })();
72 result.unwrap_or_else(|error| {
73 if lookup_sensitive {
74 uncertain(id, target.clone(), error)
75 } else {
76 request_failure(&replies.request, id, target, error)
77 }
78 })
79 }
80}
81
82pub(super) fn request_failure(
83 request: &transport::Request,
84 id: OperationID,
85 target: &TargetIdentity,
86 error: CoreError,
87) -> OperationReceipt {
88 if request.refused_before_send() {
89 buntrail_services::files::failure(id, target.clone(), error)
90 } else {
91 uncertain(id, target.clone(), error)
92 }
93}