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