1use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6use crate::postbox::Message;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(tag = "op", rename_all = "snake_case")]
10pub enum Request {
11 Put {
12 key: String,
13 value: String,
14 },
15 Get {
16 key: String,
17 },
18 Del {
19 key: String,
20 },
21 Send {
22 #[serde(default)]
23 from: Option<String>,
24 recipient: String,
25 message: String,
26 },
27 Cron {
28 schedule: String,
29 message: String,
30 },
31 Poll {
32 recipient: String,
33 },
34 PollCron,
35 List {
36 path: String,
37 },
38 Ack {
39 id_or_path: String,
40 },
41 Flush,
42 Ping,
43 Shutdown,
44 TickStart {
45 label: String,
46 },
47 TickEnd,
48 TickStatus,
49 TickLock {
50 key: String,
51 },
52 TickUnlock {
53 key: String,
54 },
55 TickPhase {
57 phase: String,
58 },
59 Event {
60 payload: String,
61 #[serde(default)]
63 ttl: Option<u64>,
64 },
65 AgentMessage {
66 from: String,
67 to: String,
68 payload: String,
69 },
70 WebStatus,
72 WebList,
74 WebRm {
76 name: String,
77 },
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81#[serde(tag = "status", rename_all = "snake_case")]
82pub enum Response {
83 Ok {
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 value: Option<String>,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 uuid: Option<Uuid>,
88 #[serde(default, skip_serializing_if = "Option::is_none")]
89 found: Option<bool>,
90 #[serde(default, skip_serializing_if = "Option::is_none")]
91 dirty: Option<bool>,
92 #[serde(default, skip_serializing_if = "Option::is_none")]
93 tick: Option<u64>,
94 #[serde(default, skip_serializing_if = "Option::is_none")]
95 queued: Option<usize>,
96 #[serde(default, skip_serializing_if = "Option::is_none")]
98 phase: Option<String>,
99 #[serde(default, skip_serializing_if = "Option::is_none")]
101 committed: Option<u64>,
102 #[serde(default, skip_serializing_if = "Option::is_none")]
104 label: Option<String>,
105 #[serde(default, skip_serializing_if = "Vec::is_empty")]
106 locked_keys: Vec<String>,
107 #[serde(default, skip_serializing_if = "Vec::is_empty")]
108 messages: Vec<MessageDto>,
109 },
110 Err {
111 error: String,
112 },
113}
114
115pub fn is_tick_socket_request(request: &Request) -> bool {
120 matches!(
121 request,
122 Request::Ping
123 | Request::TickStart { .. }
124 | Request::TickEnd
125 | Request::TickStatus
126 | Request::TickLock { .. }
127 | Request::TickUnlock { .. }
128 | Request::TickPhase { .. }
129 )
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct MessageDto {
134 pub id: Uuid,
135 pub path: String,
136 pub body: String,
137}
138
139impl From<Message> for MessageDto {
140 fn from(m: Message) -> Self {
141 Self {
142 id: m.id,
143 path: m.path.display().to_string(),
144 body: m.body,
145 }
146 }
147}
148
149impl From<MessageDto> for Message {
150 fn from(m: MessageDto) -> Self {
151 Self {
152 id: m.id,
153 path: m.path.into(),
154 body: m.body,
155 }
156 }
157}
158
159pub fn encode_response(response: &Response) -> Result<String, serde_json::Error> {
160 Ok(format!("{}\n", serde_json::to_string(response)?))
161}
162
163pub fn decode_request(line: &str) -> Result<Request, serde_json::Error> {
164 serde_json::from_str(line.trim())
165}
166
167pub fn decode_response(line: &str) -> Result<Response, serde_json::Error> {
168 serde_json::from_str(line.trim())
169}
170
171pub fn ok_empty() -> Response {
172 Response::Ok {
173 value: None,
174 uuid: None,
175 found: None,
176 dirty: None,
177 tick: None,
178 queued: None,
179 phase: None,
180 committed: None,
181 label: None,
182 locked_keys: vec![],
183 messages: vec![],
184 }
185}