Skip to main content

flashq/
types.rs

1use std::time::Duration;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::constants::*;
7
8/// Client connection options.
9#[derive(Debug, Clone)]
10pub struct ClientOptions {
11    pub host: String,
12    pub port: u16,
13    pub http_port: u16,
14    pub token: Option<String>,
15    pub timeout: Duration,
16    pub use_binary: bool,
17    pub auto_reconnect: bool,
18    pub reconnect_delay: Duration,
19    pub max_reconnect_delay: Duration,
20    pub max_reconnect_attempts: u32,
21    pub pool_size: usize,
22}
23
24impl Default for ClientOptions {
25    fn default() -> Self {
26        Self {
27            host: DEFAULT_HOST.to_string(),
28            port: DEFAULT_PORT,
29            http_port: DEFAULT_HTTP_PORT,
30            token: None,
31            timeout: DEFAULT_TIMEOUT,
32            use_binary: false,
33            auto_reconnect: true,
34            reconnect_delay: DEFAULT_RECONNECT_DELAY,
35            max_reconnect_delay: DEFAULT_MAX_RECONNECT_DELAY,
36            max_reconnect_attempts: DEFAULT_MAX_RECONNECT_ATTEMPTS,
37            pool_size: DEFAULT_POOL_SIZE,
38        }
39    }
40}
41
42/// Push options for job creation.
43#[derive(Debug, Clone, Default, Serialize)]
44pub struct PushOptions {
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub priority: Option<i32>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub delay: Option<u64>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub ttl: Option<u64>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub timeout: Option<u64>,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub max_attempts: Option<u32>,
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub backoff: Option<u64>,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub unique_key: Option<String>,
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub depends_on: Option<Vec<u64>>,
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub tags: Option<Vec<String>>,
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub lifo: Option<bool>,
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub remove_on_complete: Option<bool>,
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub remove_on_fail: Option<bool>,
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub stall_timeout: Option<u64>,
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub debounce_id: Option<String>,
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub debounce_ttl: Option<u64>,
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub job_id: Option<String>,
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub keep_completed_age: Option<u64>,
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub keep_completed_count: Option<u64>,
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub group_id: Option<String>,
83}
84
85impl PushOptions {
86    /// Merge non-None fields into a JSON command object.
87    pub fn merge_into(&self, cmd: &mut Value) {
88        let obj = cmd.as_object_mut().expect("cmd must be an object");
89        if let Ok(val) = serde_json::to_value(self) {
90            if let Some(opts_obj) = val.as_object() {
91                for (k, v) in opts_obj {
92                    obj.insert(k.clone(), v.clone());
93                }
94            }
95        }
96    }
97}
98
99/// Job data from the server.
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct Job {
102    pub id: u64,
103    pub queue: String,
104    pub data: Value,
105    #[serde(default)]
106    pub priority: i32,
107    #[serde(default)]
108    pub created_at: u64,
109    #[serde(default)]
110    pub run_at: u64,
111    #[serde(default)]
112    pub started_at: u64,
113    #[serde(default)]
114    pub attempts: u32,
115    #[serde(default)]
116    pub max_attempts: u32,
117    #[serde(default)]
118    pub backoff: u64,
119    #[serde(default)]
120    pub ttl: u64,
121    #[serde(default)]
122    pub timeout: u64,
123    #[serde(default)]
124    pub unique_key: Option<String>,
125    #[serde(default)]
126    pub depends_on: Vec<u64>,
127    #[serde(default)]
128    pub progress: u8,
129    #[serde(default)]
130    pub progress_msg: Option<String>,
131    #[serde(default)]
132    pub tags: Vec<String>,
133    #[serde(default)]
134    pub lifo: bool,
135    #[serde(default)]
136    pub remove_on_complete: bool,
137    #[serde(default)]
138    pub remove_on_fail: bool,
139    #[serde(default)]
140    pub last_heartbeat: u64,
141    #[serde(default)]
142    pub stall_timeout: u64,
143    #[serde(default)]
144    pub stall_count: u32,
145    #[serde(default)]
146    pub parent_id: Option<u64>,
147    #[serde(default)]
148    pub children_ids: Vec<u64>,
149    #[serde(default)]
150    pub children_completed: u32,
151    #[serde(default)]
152    pub custom_id: Option<String>,
153    #[serde(default)]
154    pub keep_completed_age: u64,
155    #[serde(default)]
156    pub keep_completed_count: u64,
157    #[serde(default)]
158    pub completed_at: u64,
159    #[serde(default)]
160    pub group_id: Option<String>,
161}
162
163/// Job state enum matching the server.
164#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
165#[serde(rename_all = "lowercase")]
166pub enum JobState {
167    Waiting,
168    Delayed,
169    Active,
170    Completed,
171    Failed,
172    #[serde(rename = "waiting-children")]
173    WaitingChildren,
174    #[serde(rename = "waiting-parent")]
175    WaitingParent,
176    Stalled,
177    Unknown,
178}
179
180impl std::fmt::Display for JobState {
181    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182        match self {
183            JobState::Waiting => write!(f, "waiting"),
184            JobState::Delayed => write!(f, "delayed"),
185            JobState::Active => write!(f, "active"),
186            JobState::Completed => write!(f, "completed"),
187            JobState::Failed => write!(f, "failed"),
188            JobState::WaitingChildren => write!(f, "waiting-children"),
189            JobState::WaitingParent => write!(f, "waiting-parent"),
190            JobState::Stalled => write!(f, "stalled"),
191            JobState::Unknown => write!(f, "unknown"),
192        }
193    }
194}
195
196/// Job with its current state.
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct JobWithState {
199    pub job: Job,
200    pub state: JobState,
201}
202
203/// Batch push result.
204#[derive(Debug, Clone)]
205pub struct BatchPushResult {
206    pub ids: Vec<u64>,
207}
208
209/// Job counts by state.
210#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct JobCounts {
212    #[serde(default)]
213    pub waiting: u64,
214    #[serde(default)]
215    pub active: u64,
216    #[serde(default)]
217    pub delayed: u64,
218    #[serde(default)]
219    pub completed: u64,
220    #[serde(default)]
221    pub failed: u64,
222}
223
224/// Jobs list result with total count.
225#[derive(Debug, Clone)]
226pub struct JobsResult {
227    pub jobs: Vec<JobWithState>,
228    pub total: u64,
229}
230
231/// Queue info from LISTQUEUES.
232#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct QueueInfo {
234    pub name: String,
235    #[serde(default)]
236    pub pending: u64,
237    #[serde(default)]
238    pub processing: u64,
239    #[serde(default)]
240    pub completed: u64,
241    #[serde(default)]
242    pub delayed: u64,
243    #[serde(default)]
244    pub dlq: u64,
245    #[serde(default)]
246    pub paused: bool,
247    #[serde(default)]
248    pub rate_limit: Option<u32>,
249    #[serde(default)]
250    pub concurrency_limit: Option<u32>,
251}
252
253/// Log entry for a job.
254#[derive(Debug, Clone, Serialize, Deserialize)]
255pub struct LogEntry {
256    pub timestamp: u64,
257    pub message: String,
258    pub level: String,
259}
260
261/// Progress info for a job.
262#[derive(Debug, Clone)]
263pub struct ProgressInfo {
264    pub progress: u8,
265    pub message: Option<String>,
266}
267
268/// Cron job options for creating a cron.
269#[derive(Debug, Clone, Default)]
270pub struct CronOptions {
271    pub queue: String,
272    pub data: Value,
273    pub schedule: Option<String>,
274    pub repeat_every: Option<u64>,
275    pub priority: Option<i32>,
276    pub limit: Option<u64>,
277}
278
279/// Cron job info from the server.
280#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct CronJob {
282    pub name: String,
283    pub queue: String,
284    pub data: Value,
285    #[serde(default)]
286    pub schedule: Option<String>,
287    #[serde(default)]
288    pub repeat_every: Option<u64>,
289    #[serde(default)]
290    pub priority: i32,
291    #[serde(default)]
292    pub next_run: u64,
293    #[serde(default)]
294    pub executions: u64,
295    #[serde(default)]
296    pub limit: Option<u64>,
297}
298
299/// Flow child definition.
300#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct FlowChild {
302    pub queue: String,
303    pub data: Value,
304    #[serde(default, skip_serializing_if = "Option::is_none")]
305    pub priority: Option<i32>,
306    #[serde(default, skip_serializing_if = "Option::is_none")]
307    pub delay: Option<u64>,
308}
309
310/// Flow push result.
311#[derive(Debug, Clone)]
312pub struct FlowResult {
313    pub parent_id: u64,
314    pub children_ids: Vec<u64>,
315}
316
317/// Queue statistics.
318#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct Stats {
320    #[serde(default)]
321    pub queued: u64,
322    #[serde(default)]
323    pub processing: u64,
324    #[serde(default)]
325    pub delayed: u64,
326    #[serde(default)]
327    pub dlq: u64,
328}
329
330/// Detailed metrics.
331#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct Metrics {
333    #[serde(default)]
334    pub total_pushed: u64,
335    #[serde(default)]
336    pub total_completed: u64,
337    #[serde(default)]
338    pub total_failed: u64,
339    #[serde(default)]
340    pub jobs_per_second: f64,
341    #[serde(default)]
342    pub avg_latency_ms: f64,
343    #[serde(default)]
344    pub queues: Vec<QueueMetrics>,
345}
346
347/// Per-queue metrics.
348#[derive(Debug, Clone, Serialize, Deserialize)]
349pub struct QueueMetrics {
350    pub name: String,
351    #[serde(default)]
352    pub pending: u64,
353    #[serde(default)]
354    pub processing: u64,
355    #[serde(default)]
356    pub dlq: u64,
357    #[serde(default)]
358    pub rate_limit: Option<u32>,
359}
360
361/// Worker options.
362#[derive(Debug, Clone)]
363pub struct WorkerOptions {
364    pub concurrency: usize,
365    pub batch_size: usize,
366    pub auto_start: bool,
367    pub close_timeout: Duration,
368    pub stall_timeout: Duration,
369    pub client_options: Option<ClientOptions>,
370}
371
372impl Default for WorkerOptions {
373    fn default() -> Self {
374        Self {
375            concurrency: DEFAULT_WORKER_CONCURRENCY,
376            batch_size: DEFAULT_WORKER_BATCH_SIZE,
377            auto_start: true,
378            close_timeout: DEFAULT_WORKER_CLOSE_TIMEOUT,
379            stall_timeout: Duration::from_secs(30),
380            client_options: None,
381        }
382    }
383}
384
385/// Batch job input for push_batch.
386#[derive(Debug, Clone, Serialize)]
387pub struct JobPayload {
388    pub data: Value,
389    #[serde(flatten)]
390    pub options: PushOptions,
391}
392
393/// Worker event types.
394#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
395pub enum WorkerEvent {
396    Ready,
397    Active,
398    Completed,
399    Failed,
400    Error,
401    Stopping,
402    Stopped,
403    Drained,
404}
405
406/// Bulk job for Queue.add_bulk.
407#[derive(Debug, Clone)]
408pub struct BulkJob {
409    pub name: String,
410    pub data: Value,
411    pub options: Option<PushOptions>,
412}