1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Task query criteria for filtering and searching tasks
//!
//! Provides the [`TaskQuery`] struct for building multi-criteria task filters.
use chrono::{DateTime, Utc};
use crate::types::{TaskMeta, TaskResult};
/// Query criteria for filtering tasks
#[derive(Debug, Clone, Default)]
pub struct TaskQuery {
/// Filter by task state
pub state: Option<TaskResult>,
/// Filter by worker name
pub worker: Option<String>,
/// Filter by creation time (start of range)
pub created_after: Option<DateTime<Utc>>,
/// Filter by creation time (end of range)
pub created_before: Option<DateTime<Utc>>,
/// Filter by task name pattern
pub task_name_pattern: Option<String>,
/// Filter by tags (task must have all specified tags)
pub tags: Vec<String>,
/// Filter by metadata key-value pairs (task must have all specified key-value pairs)
pub metadata: std::collections::HashMap<String, serde_json::Value>,
}
impl TaskQuery {
/// Create a new empty query
pub fn new() -> Self {
Self::default()
}
/// Filter by state
pub fn with_state(mut self, state: TaskResult) -> Self {
self.state = Some(state);
self
}
/// Filter by worker
pub fn with_worker(mut self, worker: impl Into<String>) -> Self {
self.worker = Some(worker.into());
self
}
/// Filter by creation time range
pub fn with_time_range(mut self, start: DateTime<Utc>, end: DateTime<Utc>) -> Self {
self.created_after = Some(start);
self.created_before = Some(end);
self
}
/// Filter by task name pattern (simple substring match)
pub fn with_task_name_pattern(mut self, pattern: impl Into<String>) -> Self {
self.task_name_pattern = Some(pattern.into());
self
}
/// Filter by tag (task must have this tag)
pub fn with_tag(mut self, tag: impl Into<String>) -> Self {
self.tags.push(tag.into());
self
}
/// Filter by multiple tags (task must have all specified tags)
pub fn with_tags(mut self, tags: Vec<String>) -> Self {
self.tags.extend(tags);
self
}
/// Filter by metadata field (task must have this exact key-value pair)
pub fn with_metadata(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
self.metadata.insert(key.into(), value);
self
}
/// Check if a task matches all criteria
pub fn matches(&self, meta: &TaskMeta) -> bool {
// Check state
if let Some(ref target_state) = self.state {
if !meta.result.same_variant(target_state) {
return false;
}
}
// Check worker
if let Some(ref target_worker) = self.worker {
if meta.worker.as_ref() != Some(target_worker) {
return false;
}
}
// Check creation time range
if let Some(start) = self.created_after {
if meta.created_at < start {
return false;
}
}
if let Some(end) = self.created_before {
if meta.created_at > end {
return false;
}
}
// Check task name pattern
if let Some(ref pattern) = self.task_name_pattern {
if !meta.task_name.contains(pattern) {
return false;
}
}
// Check tags (task must have all specified tags)
if !self.tags.is_empty() && !meta.has_all_tags(&self.tags) {
return false;
}
// Check metadata (task must have all specified key-value pairs)
for (key, value) in &self.metadata {
match meta.get_metadata(key) {
Some(meta_value) if meta_value == value => {}
_ => return false,
}
}
true
}
}