omry_integration/
bridge.rs1use anyhow::{Context, Result};
3use omry_service::archiving::{Record, RecordMeta, RecordParams};
4use omry_service::common::RecordId;
5use omry_service::search::SearchResponse;
6use omry_service::search_wrappers::SearchParametersWrapper;
7use omry_service::service::RecordIds;
8use omry_service::tarpc::context;
9use omry_service::{FloraServiceClient, PONG};
10use std::sync::Arc;
11use tokio::task::JoinSet;
12use tracing::instrument;
13
14#[allow(async_fn_in_trait)]
17pub trait ServiceBridge {
18 fn client(&self) -> &FloraServiceClient;
20
21 #[instrument(skip(self))]
25 async fn ping(&self) -> Result<String> {
26 let response = self.client().ping(context::current()).await?;
27 if response == PONG {
28 Ok(response)
29 } else {
30 anyhow::bail!("Unexpected ping response: {response}")
31 }
32 }
33
34 #[instrument(skip(self))]
36 async fn add_record(&self, record: RecordParams) -> Result<RecordId> {
37 let id = self
38 .client()
39 .add_record(context::current(), record)
40 .await?
41 .map_err(|e| anyhow::anyhow!("{e}"))?;
42 Ok(id)
43 }
44
45 #[instrument(skip(self))]
47 async fn count(&self) -> Result<i64> {
48 let count = self
49 .client()
50 .count(context::current())
51 .await?
52 .map_err(|e| anyhow::anyhow!("{e}"))?;
53 Ok(count)
54 }
55
56 #[instrument(skip(self))]
58 async fn get_records(&self, record_ids: RecordIds) -> Result<Arc<Vec<Record>>> {
59 let records = self
60 .client()
61 .get_records(context::current(), record_ids)
62 .await?
63 .map_err(|e| anyhow::anyhow!("{e}"))?;
64 Ok(records)
65 }
66
67 #[instrument(skip(self))]
69 async fn get_all_records_meta(&self) -> Result<Vec<RecordMeta>> {
70 let records = self
71 .client()
72 .get_all_records_meta(context::current())
73 .await
74 .context("Failed to invoke 'get_all_records_meta' RPC")?
75 .map_err(|e| anyhow::anyhow!("{e}"))?;
76
77 Ok(records)
78 }
79
80 #[instrument(skip(self))]
82 async fn search(&self, search_parameters: SearchParametersWrapper) -> Result<SearchResponse> {
83 let search_result = self
84 .client()
85 .search(context::current(), search_parameters)
86 .await?
87 .map_err(|e| anyhow::anyhow!("{e}"))?;
88
89 Ok(search_result)
90 }
91
92 #[instrument(skip(self))]
95 async fn delete(&self, ids: Vec<RecordId>) -> Result<usize> {
96 tracing::debug!(
97 "Will make {} RPCs to delete the given IDs (one per each)",
98 ids.len()
99 );
100
101 let mut set = JoinSet::new();
102 for id in ids {
103 let client = self.client().clone();
104
105 set.spawn(async move {
106 client
107 .delete_record(context::current(), id)
108 .await
109 .map_err(|error| error.to_string())
110 .flatten()
111 });
112 }
113
114 let mut n_deleted = 0usize;
115 let mut n_errors = 0usize;
116 let results = set.join_all().await;
117 for result in results {
118 match result {
119 Ok(n) => n_deleted += n,
120 Err(error) => {
121 tracing::error!("Error calling `delete_record`: {error}");
122 n_errors += 1;
123 }
124 }
125 }
126
127 if n_errors != 0 {
128 anyhow::bail!("{n_errors} records couldn't be scheduled for deletion due to errors.");
129 }
130
131 Ok(n_deleted)
132 }
133
134 #[instrument(skip(self))]
136 async fn version(&self) -> Result<String> {
137 let version = self
138 .client()
139 .version(context::current())
140 .await
141 .context("Failed to invoke 'version' RPC")?
142 .map_err(|e| anyhow::anyhow!("{e}"))?;
143
144 Ok(version)
145 }
146}