actor_core_client/
client.rs1use anyhow::Result;
2use serde_json::{json, Value};
3
4use crate::drivers::TransportKind;
5use crate::encoding::EncodingKind;
6use crate::handle::{ActorHandle, ActorHandleInner};
7
8type ActorTags = Vec<(String, String)>;
9
10pub struct CreateRequestMetadata {
11 pub tags: ActorTags,
12 pub region: Option<String>,
13}
14
15pub struct PartialCreateRequestMetadata {
16 pub tags: Option<ActorTags>,
17 pub region: Option<String>,
18}
19
20pub struct GetWithIdOptions {
21 pub params: Option<serde_json::Value>,
22}
23
24impl Default for GetWithIdOptions {
25 fn default() -> Self {
26 Self { params: None }
27 }
28}
29
30pub struct GetOptions {
31 pub tags: Option<ActorTags>,
32 pub params: Option<serde_json::Value>,
33 pub no_create: Option<bool>,
34 pub create: Option<PartialCreateRequestMetadata>,
35}
36
37impl Default for GetOptions {
38 fn default() -> Self {
39 Self {
40 tags: None,
41 params: None,
42 no_create: None,
43 create: None,
44 }
45 }
46}
47
48pub struct CreateOptions {
49 pub params: Option<serde_json::Value>,
50 pub create: CreateRequestMetadata,
51}
52
53impl Default for CreateOptions {
54 fn default() -> Self {
55 Self {
56 params: None,
57 create: CreateRequestMetadata {
58 tags: vec![],
59 region: None,
60 },
61 }
62 }
63}
64
65pub struct Client {
66 manager_endpoint: String,
67 encoding_kind: EncodingKind,
68 transport_kind: TransportKind,
69}
70
71impl Client {
72 pub fn new(
73 manager_endpoint: String,
74 transport_kind: TransportKind,
75 encoding_kind: EncodingKind,
76 ) -> Self {
77 Self {
78 manager_endpoint,
79 encoding_kind,
80 transport_kind,
81 }
82 }
83
84 async fn post_manager_endpoint(&self, path: &str, body: Value) -> Result<Value> {
85 let client = reqwest::Client::new();
86 let req = client.post(format!("{}{}", self.manager_endpoint, path));
87 let req = req.header("Content-Type", "application/json");
88 let req = req.body(serde_json::to_string(&body)?);
89 let res = req.send().await?;
90 let body = res.text().await?;
91
92 let body: Value = serde_json::from_str(&body)?;
93
94 Ok(body)
95 }
96
97 #[allow(dead_code)]
98 async fn get_manager_endpoint(&self, path: &str) -> Result<Value> {
99 let client = reqwest::Client::new();
100 let req = client.get(format!("{}{}", self.manager_endpoint, path));
101 let res = req.send().await?;
102 let body = res.text().await?;
103 let body: Value = serde_json::from_str(&body)?;
104
105 Ok(body)
106 }
107
108 pub async fn get(&self, name: &str, opts: GetOptions) -> Result<ActorHandle> {
109 let tags_map: serde_json::Map<String, Value> = opts.tags
111 .unwrap_or_default()
112 .into_iter()
113 .map(|(k, v)| (k, json!(v)))
114 .collect();
115
116 let create = if !opts.no_create.unwrap_or(false) {
118 if let Some(create_opts) = &opts.create {
120 let create_tags = if let Some(tags) = &create_opts.tags {
122 tags.iter()
123 .map(|(k, v)| (k.clone(), json!(v.clone())))
124 .collect()
125 } else {
126 tags_map.clone()
127 };
128
129 let mut create_obj = json!({
131 "name": name,
132 "tags": create_tags
133 });
134
135 if let Some(region) = &create_opts.region {
136 create_obj["region"] = json!(region.clone());
137 }
138
139 Some(create_obj)
140 } else {
141 Some(json!({
143 "name": name,
144 "tags": tags_map
145 }))
146 }
147 } else {
148 None
149 };
150
151 let body = json!({
153 "query": {
154 "getOrCreateForTags": {
155 "name": name,
156 "tags": tags_map,
157 "create": create
158 }
159 }
160 });
161 let res_json = self.post_manager_endpoint("/manager/actors", body).await?;
162 let Some(endpoint) = res_json["endpoint"].as_str() else {
163 return Err(anyhow::anyhow!(
164 "No endpoint returned. Request failed? {:?}",
165 res_json
166 ));
167 };
168
169 let handle = ActorHandleInner::new(
170 endpoint.to_string(),
171 self.transport_kind,
172 self.encoding_kind,
173 opts.params,
174 )?;
175 handle.start_connection().await;
176
177 Ok(handle)
178 }
179
180 pub async fn get_with_id(&self, actor_id: &str, opts: GetWithIdOptions) -> Result<ActorHandle> {
181 let body = json!({
182 "query": {
183 "getForId": {
184 "actorId": actor_id,
185 }
186 },
187 });
188 let res_json = self.post_manager_endpoint("/manager/actors", body).await?;
189 let Some(endpoint) = res_json["endpoint"].as_str() else {
190 return Err(anyhow::anyhow!(
191 "No endpoint returned. Request failed? {:?}",
192 res_json
193 ));
194 };
195
196 let handle = ActorHandleInner::new(
197 endpoint.to_string(),
198 self.transport_kind,
199 self.encoding_kind,
200 opts.params,
201 )?;
202 handle.start_connection().await;
203
204 Ok(handle)
205 }
206
207 pub async fn create(&self, name: &str, opts: CreateOptions) -> Result<ActorHandle> {
208 let mut tag_map = serde_json::Map::new();
209
210 for (key, value) in opts.create.tags {
211 tag_map.insert(key, json!(value));
212 }
213
214 let mut req_body = serde_json::Map::new();
215 req_body.insert("name".to_string(), json!(name.to_string()));
216 req_body.insert("tags".to_string(), json!(tag_map));
217 if let Some(region) = opts.create.region {
218 req_body.insert("region".to_string(), json!(region));
219 }
220
221 let body = json!({
222 "query": {
223 "create": req_body
224 },
225 });
226 let res_json = self.post_manager_endpoint("/manager/actors", body).await?;
227 let Some(endpoint) = res_json["endpoint"].as_str() else {
228 return Err(anyhow::anyhow!(
229 "No endpoint returned. Request failed? {:?}",
230 res_json
231 ));
232 };
233
234 let handle = ActorHandleInner::new(
235 endpoint.to_string(),
236 self.transport_kind,
237 self.encoding_kind,
238 opts.params,
239 )?;
240 handle.start_connection().await;
241
242 Ok(handle)
243 }
244}