1use std::{collections::HashMap, sync::Arc};
2
3use anyhow::Result;
4use serde_json::Value as JsonValue;
5
6use crate::{
7 common::{ActorKey, EncodingKind, TransportKind},
8 handle::ActorHandle,
9 protocol::query::*,
10 remote_manager::RemoteManager,
11};
12
13#[derive(Default)]
14pub struct GetWithIdOptions {
15 pub params: Option<JsonValue>,
16}
17
18#[derive(Default)]
19pub struct GetOptions {
20 pub params: Option<JsonValue>,
21}
22
23#[derive(Default)]
24pub struct GetOrCreateOptions {
25 pub params: Option<JsonValue>,
26 pub create_in_region: Option<String>,
27 pub create_with_input: Option<JsonValue>,
28 pub pool_name: Option<String>,
30}
31
32#[derive(Default)]
33pub struct CreateOptions {
34 pub params: Option<JsonValue>,
35 pub region: Option<String>,
36 pub input: Option<JsonValue>,
37 pub pool_name: Option<String>,
39}
40
41pub struct ClientConfig {
42 pub endpoint: String,
43 pub token: Option<String>,
44 pub namespace: Option<String>,
45 pub pool_name: Option<String>,
46 pub encoding: EncodingKind,
47 pub transport: TransportKind,
48 pub headers: Option<HashMap<String, String>>,
49 pub max_input_size: Option<usize>,
50 pub disable_metadata_lookup: bool,
51}
52
53impl ClientConfig {
54 pub fn new(endpoint: impl Into<String>) -> Self {
55 Self {
56 endpoint: endpoint.into(),
57 token: None,
58 namespace: None,
59 pool_name: None,
60 encoding: EncodingKind::Bare,
61 transport: TransportKind::WebSocket,
62 headers: None,
63 max_input_size: None,
64 disable_metadata_lookup: false,
65 }
66 }
67
68 pub fn token(mut self, token: impl Into<String>) -> Self {
69 self.token = Some(token.into());
70 self
71 }
72
73 pub fn token_opt(mut self, token: Option<String>) -> Self {
74 self.token = token;
75 self
76 }
77
78 pub fn namespace(mut self, namespace: impl Into<String>) -> Self {
79 self.namespace = Some(namespace.into());
80 self
81 }
82
83 pub fn pool_name(mut self, pool_name: impl Into<String>) -> Self {
84 self.pool_name = Some(pool_name.into());
85 self
86 }
87
88 pub fn encoding(mut self, encoding: EncodingKind) -> Self {
89 self.encoding = encoding;
90 self
91 }
92
93 pub fn transport(mut self, transport: TransportKind) -> Self {
94 self.transport = transport;
95 self
96 }
97
98 pub fn header(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
99 self.headers
100 .get_or_insert_with(HashMap::new)
101 .insert(key.into(), value.into());
102 self
103 }
104
105 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
106 self.headers = Some(headers);
107 self
108 }
109
110 pub fn max_input_size(mut self, max_input_size: usize) -> Self {
111 self.max_input_size = Some(max_input_size);
112 self
113 }
114
115 pub fn disable_metadata_lookup(mut self, disable: bool) -> Self {
116 self.disable_metadata_lookup = disable;
117 self
118 }
119}
120
121pub struct Client {
122 remote_manager: RemoteManager,
123 encoding_kind: EncodingKind,
124 transport_kind: TransportKind,
125 shutdown_tx: Arc<tokio::sync::broadcast::Sender<()>>,
126}
127
128impl Clone for Client {
129 fn clone(&self) -> Self {
130 Self {
131 remote_manager: self.remote_manager.clone(),
132 encoding_kind: self.encoding_kind,
133 transport_kind: self.transport_kind,
134 shutdown_tx: self.shutdown_tx.clone(),
135 }
136 }
137}
138
139impl std::fmt::Debug for Client {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 f.debug_struct("Client")
142 .field("encoding_kind", &self.encoding_kind)
143 .field("transport_kind", &self.transport_kind)
144 .finish_non_exhaustive()
145 }
146}
147
148impl Client {
149 pub fn new(config: ClientConfig) -> Self {
150 let remote_manager = RemoteManager::from_config(
151 config.endpoint,
152 config.token,
153 config.namespace,
154 config.pool_name,
155 config.headers,
156 config.max_input_size,
157 config.disable_metadata_lookup,
158 );
159
160 Self {
161 remote_manager,
162 encoding_kind: config.encoding,
163 transport_kind: config.transport,
164 shutdown_tx: Arc::new(tokio::sync::broadcast::channel(1).0),
165 }
166 }
167
168 pub fn from_endpoint(endpoint: impl Into<String>) -> Self {
169 Self::new(ClientConfig::new(endpoint))
170 }
171
172 fn create_handle(&self, params: Option<JsonValue>, query: ActorQuery) -> ActorHandle {
173 let handle = ActorHandle::new(
174 self.remote_manager.clone(),
175 params,
176 query,
177 self.shutdown_tx.clone(),
178 self.transport_kind,
179 self.encoding_kind,
180 );
181
182 handle
183 }
184
185 pub fn get(&self, name: &str, key: ActorKey, opts: GetOptions) -> Result<ActorHandle> {
186 let actor_query = ActorQuery::GetForKey {
187 get_for_key: GetForKeyRequest {
188 name: name.to_string(),
189 key,
190 },
191 };
192
193 let handle = self.create_handle(opts.params, actor_query);
194
195 Ok(handle)
196 }
197
198 pub fn get_for_id(&self, name: &str, actor_id: &str, opts: GetOptions) -> Result<ActorHandle> {
199 let actor_query = ActorQuery::GetForId {
200 get_for_id: GetForIdRequest {
201 name: name.to_string(),
202 actor_id: actor_id.to_string(),
203 },
204 };
205
206 let handle = self.create_handle(opts.params, actor_query);
207
208 Ok(handle)
209 }
210
211 pub fn get_or_create(
212 &self,
213 name: &str,
214 key: ActorKey,
215 opts: GetOrCreateOptions,
216 ) -> Result<ActorHandle> {
217 let input = opts.create_with_input;
218 let region = opts.create_in_region;
219
220 let actor_query = ActorQuery::GetOrCreateForKey {
221 get_or_create_for_key: GetOrCreateRequest {
222 name: name.to_string(),
223 key: key,
224 input,
225 region,
226 pool_name: opts.pool_name,
227 },
228 };
229
230 let handle = self.create_handle(opts.params, actor_query);
231
232 Ok(handle)
233 }
234
235 pub async fn create(
236 &self,
237 name: &str,
238 key: ActorKey,
239 opts: CreateOptions,
240 ) -> Result<ActorHandle> {
241 let input = opts.input;
242 let _region = opts.region;
243
244 let actor_id = self
245 .remote_manager
246 .create_actor(name, &key, input, opts.pool_name)
247 .await?;
248
249 let get_query = ActorQuery::GetForId {
250 get_for_id: GetForIdRequest {
251 name: name.to_string(),
252 actor_id,
253 },
254 };
255
256 let handle = self.create_handle(opts.params, get_query);
257
258 Ok(handle)
259 }
260
261 pub fn disconnect(self) {
262 drop(self)
263 }
264
265 pub fn dispose(self) {
266 self.disconnect()
267 }
268}
269
270impl Drop for Client {
271 fn drop(&mut self) {
272 let _ = self.shutdown_tx.send(());
274 }
275}