1use std::time::SystemTime;
7
8use crate::engine::{Tx, group_key, ns};
9use crate::{Result, Store, to_ms};
10
11pub struct Tasks<'a> {
12 store: &'a Store,
13}
14
15impl<'a> Tasks<'a> {
16 pub(crate) fn new(store: &'a Store) -> Self {
17 Self { store }
18 }
19
20 pub fn kv_get(&self, key: impl AsRef<[u8]>) -> Result<Option<Vec<u8>>> {
23 Ok(self.store.get(ns::KV, key.as_ref())?.map(|(_, v)| v))
24 }
25
26 pub fn kv_put(&self, key: impl AsRef<[u8]>, value: &[u8]) -> Result<()> {
27 self.store
28 .put(ns::KV, key.as_ref(), value, now_ms())
29 .map(drop)
30 }
31
32 pub fn kv_delete(&self, key: impl AsRef<[u8]>) -> Result<bool> {
34 self.store.delete(ns::KV, key.as_ref())
35 }
36
37 pub fn kv_keys(&self, prefix: impl AsRef<[u8]>) -> Result<Vec<Vec<u8>>> {
39 let p = prefix.as_ref();
40 self.store.keys(ns::KV, |k| k.starts_with(p))
41 }
42
43 pub fn list_push(&self, list: impl AsRef<[u8]>, item: &[u8]) -> Result<u64> {
47 let r = list_push(
48 &mut self.store.tx(),
49 ns::LIST_ITEM,
50 list.as_ref(),
51 item,
52 now_ms(),
53 );
54 self.store.finish();
55 r
56 }
57
58 pub fn list_pop_front(&self, list: impl AsRef<[u8]>) -> Result<Option<Vec<u8>>> {
60 let list = list.as_ref();
61 let mut tx = self.store.tx();
62 let Some((seq, item)) = list_front(&tx, ns::LIST_ITEM, list)? else {
63 return Ok(None);
64 };
65 tx.delete(ns::LIST_ITEM, &group_key(list, &seq.to_be_bytes())?)?;
66 drop(tx);
67 self.store.finish();
68 Ok(Some(item))
69 }
70
71 pub fn list_front(&self, list: impl AsRef<[u8]>) -> Result<Option<Vec<u8>>> {
72 let tx = self.store.tx();
73 Ok(list_front(&tx, ns::LIST_ITEM, list.as_ref())?.map(|(_, v)| v))
74 }
75
76 pub fn list_len(&self, list: impl AsRef<[u8]>) -> u64 {
77 self.store
78 .group(ns::LIST_ITEM, list.as_ref())
79 .map_or(0, |g| g.live)
80 }
81
82 pub fn list_items(&self, list: impl AsRef<[u8]>, limit: usize) -> Result<Vec<Vec<u8>>> {
84 Ok(list_scan(self.store, ns::LIST_ITEM, list.as_ref(), limit)?
85 .into_iter()
86 .map(|(_, _, v)| v)
87 .collect())
88 }
89
90 pub fn list_range(
93 &self,
94 list: impl AsRef<[u8]>,
95 from: u64,
96 limit: usize,
97 ) -> Result<Vec<Vec<u8>>> {
98 let list = list.as_ref();
99 let mut out = Vec::new();
100 let Some(g) = self.store.group(ns::LIST_ITEM, list) else {
101 return Ok(out);
102 };
103 for seq in from.max(g.head)..g.next {
104 if out.len() >= limit {
105 break;
106 }
107 if let Some((_, v)) = self
108 .store
109 .get(ns::LIST_ITEM, &group_key(list, &seq.to_be_bytes())?)?
110 {
111 out.push(v);
112 }
113 }
114 Ok(out)
115 }
116
117 pub fn list_clear(&self, list: impl AsRef<[u8]>) -> Result<u64> {
119 let list = list.as_ref();
120 let mut tx = self.store.tx();
121 let mut n = 0;
122 if let Some(g) = tx.group(ns::LIST_ITEM, list) {
123 for seq in g.head..g.next {
124 if tx.delete(ns::LIST_ITEM, &group_key(list, &seq.to_be_bytes())?)? {
125 n += 1;
126 }
127 }
128 }
129 drop(tx);
130 self.store.finish();
131 Ok(n)
132 }
133
134 pub fn set_insert(&self, set: impl AsRef<[u8]>, member: impl AsRef<[u8]>) -> Result<bool> {
138 let key = group_key(set.as_ref(), member.as_ref())?;
139 let mut tx = self.store.tx();
140 if tx.contains(ns::SET_MEMBER, &key)? {
141 return Ok(false);
142 }
143 tx.put(ns::SET_MEMBER, &key, &[], now_ms())?;
144 drop(tx);
145 self.store.finish();
146 Ok(true)
147 }
148
149 pub fn set_contains(&self, set: impl AsRef<[u8]>, member: impl AsRef<[u8]>) -> Result<bool> {
150 let key = group_key(set.as_ref(), member.as_ref())?;
151 self.store.contains(ns::SET_MEMBER, &key)
152 }
153
154 pub fn set_remove(&self, set: impl AsRef<[u8]>, member: impl AsRef<[u8]>) -> Result<bool> {
155 let key = group_key(set.as_ref(), member.as_ref())?;
156 self.store.delete(ns::SET_MEMBER, &key)
157 }
158
159 pub fn set_len(&self, set: impl AsRef<[u8]>) -> u64 {
160 self.store
161 .group(ns::SET_MEMBER, set.as_ref())
162 .map_or(0, |g| g.live)
163 }
164
165 pub fn set_members(&self, set: impl AsRef<[u8]>) -> Result<Vec<Vec<u8>>> {
167 let prefix = group_key(set.as_ref(), &[])?;
168 Ok(self
169 .store
170 .keys(ns::SET_MEMBER, |k| k.starts_with(&prefix))?
171 .into_iter()
172 .map(|k| k[prefix.len()..].to_vec())
173 .collect())
174 }
175
176 pub fn set_clear(&self, set: impl AsRef<[u8]>) -> Result<u64> {
178 let set = set.as_ref();
179 let mut n = 0;
180 for m in self.set_members(set)? {
181 if self.set_remove(set, &m)? {
182 n += 1;
183 }
184 }
185 Ok(n)
186 }
187}
188
189fn now_ms() -> u64 {
190 to_ms(SystemTime::now())
191}
192
193pub(crate) fn list_push(tx: &mut Tx<'_>, n: u8, list: &[u8], item: &[u8], ts: u64) -> Result<u64> {
194 let seq = tx.group(n, list).map_or(0, |g| g.next);
195 tx.put(n, &group_key(list, &seq.to_be_bytes())?, item, ts)?;
196 Ok(seq)
197}
198
199fn list_front(tx: &Tx<'_>, n: u8, list: &[u8]) -> Result<Option<(u64, Vec<u8>)>> {
201 let Some(g) = tx.group(n, list) else {
202 return Ok(None);
203 };
204 for seq in g.head..g.next {
205 if let Some((_, v)) = tx.get(n, &group_key(list, &seq.to_be_bytes())?)? {
206 if seq != g.head {
207 tx.set_head(n, list, seq);
208 }
209 return Ok(Some((seq, v)));
210 }
211 }
212 Ok(None)
213}
214
215pub(crate) fn list_scan(
217 store: &Store,
218 n: u8,
219 list: &[u8],
220 limit: usize,
221) -> Result<Vec<(u64, u64, Vec<u8>)>> {
222 let mut out = Vec::new();
223 let Some(g) = store.group(n, list) else {
224 return Ok(out);
225 };
226 for seq in g.head..g.next {
227 if out.len() >= limit || out.len() as u64 >= g.live {
228 break;
229 }
230 if let Some((ts, v)) = store.get(n, &group_key(list, &seq.to_be_bytes())?)? {
231 out.push((seq, ts, v));
232 }
233 }
234 Ok(out)
235}