1use std::collections::HashMap;
2use std::ops::{Deref, DerefMut};
3
4use anyhow::Result;
5use serde::{Deserialize, Serialize};
6
7use crate::actor::connection::ConnHandle;
8use crate::actor::lifecycle_hooks::Reply;
9use crate::actor::task_types::ShutdownKind;
10use crate::error::ProtocolError;
11use crate::types::ConnId;
12use crate::websocket::WebSocket;
13
14#[derive(Clone, Debug)]
15pub struct Request(http::Request<Vec<u8>>);
16
17impl Request {
18 pub fn new(body: Vec<u8>) -> Self {
19 Self(http::Request::new(body))
20 }
21
22 pub fn from_parts(
23 method: &str,
24 uri: &str,
25 headers: HashMap<String, String>,
26 body: Vec<u8>,
27 ) -> Result<Self> {
28 let method = method
29 .parse::<http::Method>()
30 .map_err(|error| invalid_http_request("method", format!("{method}: {error}")))?;
31 let uri = uri
32 .parse::<http::Uri>()
33 .map_err(|error| invalid_http_request("uri", format!("{uri}: {error}")))?;
34 let mut request = http::Request::builder()
35 .method(method)
36 .uri(uri)
37 .body(body)?;
38
39 for (name, value) in headers {
40 let header_name: http::header::HeaderName = name
41 .parse()
42 .map_err(|error| invalid_http_request("header name", format!("{name}: {error}")))?;
43 let header_value: http::header::HeaderValue = value.parse().map_err(|error| {
44 invalid_http_request("header value", format!("{name}: {error}"))
45 })?;
46 request.headers_mut().insert(header_name, header_value);
47 }
48
49 Ok(Self(request))
50 }
51
52 pub fn to_parts(&self) -> (String, String, HashMap<String, String>, Vec<u8>) {
53 (
54 self.method().to_string(),
55 self.uri().to_string(),
56 self.headers()
57 .iter()
58 .map(|(name, value)| {
59 (
60 name.to_string(),
61 String::from_utf8_lossy(value.as_bytes()).into_owned(),
62 )
63 })
64 .collect(),
65 self.body().clone(),
66 )
67 }
68
69 pub fn into_inner(self) -> http::Request<Vec<u8>> {
70 self.0
71 }
72
73 pub fn into_body(self) -> Vec<u8> {
74 self.0.into_body()
75 }
76}
77
78impl Default for Request {
79 fn default() -> Self {
80 Self::new(Vec::new())
81 }
82}
83
84impl Deref for Request {
85 type Target = http::Request<Vec<u8>>;
86
87 fn deref(&self) -> &Self::Target {
88 &self.0
89 }
90}
91
92impl DerefMut for Request {
93 fn deref_mut(&mut self) -> &mut Self::Target {
94 &mut self.0
95 }
96}
97
98impl From<http::Request<Vec<u8>>> for Request {
99 fn from(value: http::Request<Vec<u8>>) -> Self {
100 Self(value)
101 }
102}
103
104impl From<Request> for http::Request<Vec<u8>> {
105 fn from(value: Request) -> Self {
106 value.0
107 }
108}
109
110#[derive(Clone, Debug)]
111pub struct Response(http::Response<Vec<u8>>);
112
113impl Response {
114 pub fn new(body: Vec<u8>) -> Self {
115 Self(http::Response::new(body))
116 }
117
118 pub fn from_parts(
119 status: u16,
120 headers: HashMap<String, String>,
121 body: Vec<u8>,
122 ) -> Result<Self> {
123 let mut response = http::Response::new(body);
124 *response.status_mut() = status
125 .try_into()
126 .map_err(|error| invalid_http_response("status", format!("{status}: {error}")))?;
127
128 for (name, value) in headers {
129 let header_name: http::header::HeaderName = name.parse().map_err(|error| {
130 invalid_http_response("header name", format!("{name}: {error}"))
131 })?;
132 let header_value: http::header::HeaderValue = value.parse().map_err(|error| {
133 invalid_http_response("header value", format!("{name}: {error}"))
134 })?;
135 response.headers_mut().insert(header_name, header_value);
136 }
137
138 Ok(Self(response))
139 }
140
141 pub fn to_parts(&self) -> (u16, HashMap<String, String>, Vec<u8>) {
142 (
143 self.status().as_u16(),
144 self.headers()
145 .iter()
146 .map(|(name, value)| {
147 (
148 name.to_string(),
149 String::from_utf8_lossy(value.as_bytes()).into_owned(),
150 )
151 })
152 .collect(),
153 self.body().clone(),
154 )
155 }
156
157 pub fn into_inner(self) -> http::Response<Vec<u8>> {
158 self.0
159 }
160
161 pub fn into_body(self) -> Vec<u8> {
162 self.0.into_body()
163 }
164}
165
166fn invalid_http_request(field: &str, reason: String) -> anyhow::Error {
167 ProtocolError::InvalidHttpRequest {
168 field: field.to_owned(),
169 reason,
170 }
171 .build()
172}
173
174fn invalid_http_response(field: &str, reason: String) -> anyhow::Error {
175 ProtocolError::InvalidHttpResponse {
176 field: field.to_owned(),
177 reason,
178 }
179 .build()
180}
181
182impl Default for Response {
183 fn default() -> Self {
184 Self::new(Vec::new())
185 }
186}
187
188impl Deref for Response {
189 type Target = http::Response<Vec<u8>>;
190
191 fn deref(&self) -> &Self::Target {
192 &self.0
193 }
194}
195
196impl DerefMut for Response {
197 fn deref_mut(&mut self) -> &mut Self::Target {
198 &mut self.0
199 }
200}
201
202impl From<http::Response<Vec<u8>>> for Response {
203 fn from(value: http::Response<Vec<u8>>) -> Self {
204 Self(value)
205 }
206}
207
208impl From<Response> for http::Response<Vec<u8>> {
209 fn from(value: Response) -> Self {
210 value.0
211 }
212}
213
214#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
215pub enum StateDelta {
216 ActorState(Vec<u8>),
217 ConnHibernation { conn: ConnId, bytes: Vec<u8> },
218 ConnHibernationRemoved(ConnId),
219}
220
221impl StateDelta {
222 pub(crate) fn payload_len(&self) -> usize {
223 match self {
224 Self::ActorState(bytes) | Self::ConnHibernation { bytes, .. } => bytes.len(),
225 Self::ConnHibernationRemoved(_) => 0,
226 }
227 }
228}
229
230#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
231pub enum SerializeStateReason {
232 Save,
233 Inspector,
234}
235
236impl SerializeStateReason {
237 pub(crate) fn label(self) -> &'static str {
238 match self {
239 Self::Save => "save",
240 Self::Inspector => "inspector",
241 }
242 }
243}
244
245#[derive(Clone, Debug, PartialEq, Eq)]
246pub enum QueueSendStatus {
247 Completed,
248 TimedOut,
249}
250
251impl QueueSendStatus {
252 pub(crate) fn as_str(&self) -> &'static str {
253 match self {
254 Self::Completed => "completed",
255 Self::TimedOut => "timedOut",
256 }
257 }
258}
259
260#[derive(Clone, Debug, PartialEq, Eq)]
261pub struct QueueSendResult {
262 pub status: QueueSendStatus,
263 pub response: Option<Vec<u8>>,
264}
265
266#[derive(Debug)]
267pub enum ActorEvent {
268 Action {
269 name: String,
270 args: Vec<u8>,
271 conn: Option<ConnHandle>,
272 reply: Reply<Vec<u8>>,
273 },
274 HttpRequest {
275 request: Request,
276 reply: Reply<Response>,
277 },
278 QueueSend {
279 name: String,
280 body: Vec<u8>,
281 conn: ConnHandle,
282 request: Request,
283 wait: bool,
284 timeout_ms: Option<u64>,
285 reply: Reply<QueueSendResult>,
286 },
287 WebSocketOpen {
288 conn: ConnHandle,
289 ws: WebSocket,
290 request: Option<Request>,
291 reply: Reply<()>,
292 },
293 ConnectionPreflight {
294 conn: ConnHandle,
295 params: Vec<u8>,
296 request: Option<Request>,
297 reply: Reply<()>,
298 },
299 ConnectionOpen {
300 conn: ConnHandle,
301 request: Option<Request>,
302 reply: Reply<()>,
303 },
304 ConnectionClosed {
305 conn: ConnHandle,
306 },
307 SubscribeRequest {
308 conn: ConnHandle,
309 event_name: String,
310 reply: Reply<()>,
311 },
312 SerializeState {
313 reason: SerializeStateReason,
314 reply: Reply<Vec<StateDelta>>,
315 },
316 RunGracefulCleanup {
317 reason: ShutdownKind,
318 reply: Reply<()>,
319 },
320 DisconnectConn {
321 conn_id: ConnId,
322 reply: Reply<()>,
323 },
324 #[cfg(test)]
325 BeginSleep,
326 #[cfg(test)]
327 FinalizeSleep {
328 reply: Reply<()>,
329 },
330 #[cfg(test)]
331 Destroy {
332 reply: Reply<()>,
333 },
334 WorkflowHistoryRequested {
335 reply: Reply<Option<Vec<u8>>>,
336 },
337 WorkflowReplayRequested {
338 entry_id: Option<String>,
339 reply: Reply<Option<Vec<u8>>>,
340 },
341}
342
343impl ActorEvent {
344 pub(crate) fn kind(&self) -> &'static str {
345 match self {
346 Self::Action { .. } => "action",
347 Self::HttpRequest { .. } => "http_request",
348 Self::QueueSend { .. } => "queue_send",
349 Self::WebSocketOpen { .. } => "websocket_open",
350 Self::ConnectionPreflight { .. } => "connection_preflight",
351 Self::ConnectionOpen { .. } => "connection_open",
352 Self::ConnectionClosed { .. } => "connection_closed",
353 Self::SubscribeRequest { .. } => "subscribe_request",
354 Self::SerializeState { reason, .. } => match reason {
355 SerializeStateReason::Save => "serialize_state_save",
356 SerializeStateReason::Inspector => "serialize_state_inspector",
357 },
358 Self::RunGracefulCleanup { reason, .. } => match reason {
359 ShutdownKind::Sleep => "run_sleep_cleanup",
360 ShutdownKind::Destroy => "run_destroy_cleanup",
361 },
362 Self::DisconnectConn { .. } => "disconnect_conn",
363 #[cfg(test)]
364 Self::BeginSleep => "begin_sleep",
365 #[cfg(test)]
366 Self::FinalizeSleep { .. } => "finalize_sleep",
367 #[cfg(test)]
368 Self::Destroy { .. } => "destroy",
369 Self::WorkflowHistoryRequested { .. } => "workflow_history_requested",
370 Self::WorkflowReplayRequested { .. } => "workflow_replay_requested",
371 }
372 }
373}
374
375#[cfg(test)]
377#[path = "../../tests/messages.rs"]
378mod tests;