1use chrono::{DateTime, Utc};
2#[cfg(any(feature = "postgres", feature = "sqlite", feature = "mysql"))]
3use keepsake::{RelationDefinition, RelationId, RelationSpec};
4#[cfg(all(
5 any(feature = "postgres", feature = "sqlite", feature = "mysql"),
6 feature = "fulfillment-counters"
7))]
8use uuid::Uuid;
9
10#[cfg(all(
11 any(feature = "postgres", feature = "sqlite", feature = "mysql"),
12 feature = "fulfillment-counters"
13))]
14use super::FulfilledExpiryCandidate;
15#[cfg(feature = "mysql")]
16use super::MySqlBackend;
17#[cfg(feature = "postgres")]
18use super::PostgresBackend;
19#[cfg(feature = "sqlite")]
20use super::SqliteBackend;
21use super::{KeepsakeSqlxBackend, NoopRelationCache, SqlxKeepsakeRepository};
22
23#[derive(Debug, Clone, Copy)]
29pub struct TimedSqlxKeepsakeRepository<'repo, B, C = NoopRelationCache>
30where
31 B: KeepsakeSqlxBackend,
32{
33 pub(super) repository: &'repo SqlxKeepsakeRepository<B, C>,
34 pub(super) at: DateTime<Utc>,
35}
36
37#[cfg(feature = "postgres")]
39pub type TimedKeepsakeRepository<'repo, C = NoopRelationCache> =
40 TimedSqlxKeepsakeRepository<'repo, PostgresBackend, C>;
41
42#[cfg(feature = "sqlite")]
44pub type TimedSqliteKeepsakeRepository<'repo, C = NoopRelationCache> =
45 TimedSqlxKeepsakeRepository<'repo, SqliteBackend, C>;
46
47#[cfg(feature = "mysql")]
49pub type TimedMySqlKeepsakeRepository<'repo, C = NoopRelationCache> =
50 TimedSqlxKeepsakeRepository<'repo, MySqlBackend, C>;
51
52impl<'repo, B, C> TimedSqlxKeepsakeRepository<'repo, B, C>
53where
54 B: KeepsakeSqlxBackend,
55{
56 #[must_use]
58 pub const fn repository(&self) -> &'repo SqlxKeepsakeRepository<B, C> {
59 self.repository
60 }
61
62 #[must_use]
64 pub const fn timestamp(&self) -> DateTime<Utc> {
65 self.at
66 }
67}
68
69#[cfg(feature = "postgres")]
70impl<C> TimedKeepsakeRepository<'_, C>
71where
72 C: super::RelationCache,
73{
74 pub async fn upsert_relation(
76 &self,
77 relation: &RelationDefinition,
78 ) -> super::RepositoryResult<RelationDefinition> {
79 self.repository.upsert_relation(relation, self.at).await
80 }
81
82 pub async fn upsert_relation_spec<Spec>(&self) -> super::RepositoryResult<RelationDefinition>
84 where
85 Spec: RelationSpec,
86 {
87 self.repository.upsert_relation_spec::<Spec>(self.at).await
88 }
89
90 pub async fn set_relation_enabled(
92 &self,
93 relation_id: RelationId,
94 enabled: bool,
95 ) -> super::RepositoryResult<bool> {
96 self.repository
97 .set_relation_enabled(relation_id, enabled, self.at)
98 .await
99 }
100
101 pub async fn due_timed_expiry(
103 &self,
104 limit: i64,
105 ) -> super::RepositoryResult<Vec<super::TimedExpiryCandidate>> {
106 self.repository.due_timed_expiry(self.at, limit).await
107 }
108
109 pub async fn expire_due_timed(&self, limit: i64) -> super::RepositoryResult<u64> {
111 self.repository.expire_due_timed(self.at, limit).await
112 }
113
114 #[cfg(feature = "fulfillment-counters")]
116 pub async fn fulfillment_snapshot(
117 &self,
118 keepsake_id: Uuid,
119 ) -> super::RepositoryResult<keepsake::FulfillmentSnapshot> {
120 self.repository.fulfillment_snapshot(keepsake_id).await
121 }
122
123 #[cfg(feature = "fulfillment-counters")]
125 pub async fn due_fulfilled_expiry(
126 &self,
127 limit: i64,
128 ) -> super::RepositoryResult<Vec<FulfilledExpiryCandidate>> {
129 self.repository.due_fulfilled_expiry(limit).await
130 }
131
132 #[cfg(feature = "fulfillment-counters")]
134 pub async fn expire_due_fulfilled(&self, limit: i64) -> super::RepositoryResult<u64> {
135 self.repository.expire_due_fulfilled(self.at, limit).await
136 }
137
138 #[cfg(feature = "fulfillment-counters")]
140 pub async fn upsert_counter_projection(
141 &self,
142 keepsake_id: Uuid,
143 key: &str,
144 value: i64,
145 ) -> super::RepositoryResult<()> {
146 self.repository
147 .upsert_counter_projection(keepsake_id, key, value, self.at)
148 .await
149 }
150
151 #[cfg(feature = "fulfillment-counters")]
153 pub async fn increment_counter_projection(
154 &self,
155 keepsake_id: Uuid,
156 key: &str,
157 delta: i64,
158 ) -> super::RepositoryResult<i64> {
159 self.repository
160 .increment_counter_projection(keepsake_id, key, delta, self.at)
161 .await
162 }
163
164 #[cfg(feature = "fulfillment-counters")]
166 pub async fn upsert_checklist_projection(
167 &self,
168 keepsake_id: Uuid,
169 item: &str,
170 complete: bool,
171 ) -> super::RepositoryResult<()> {
172 self.repository
173 .upsert_checklist_projection(keepsake_id, item, complete, self.at)
174 .await
175 }
176}
177
178#[cfg(feature = "sqlite")]
179impl<C> TimedSqliteKeepsakeRepository<'_, C>
180where
181 C: super::RelationCache,
182{
183 pub async fn upsert_relation(
185 &self,
186 relation: &RelationDefinition,
187 ) -> super::RepositoryResult<RelationDefinition> {
188 self.repository.upsert_relation(relation, self.at).await
189 }
190
191 pub async fn upsert_relation_spec<Spec>(&self) -> super::RepositoryResult<RelationDefinition>
193 where
194 Spec: RelationSpec,
195 {
196 self.repository.upsert_relation_spec::<Spec>(self.at).await
197 }
198
199 pub async fn set_relation_enabled(
201 &self,
202 relation_id: RelationId,
203 enabled: bool,
204 ) -> super::RepositoryResult<bool> {
205 self.repository
206 .set_relation_enabled(relation_id, enabled, self.at)
207 .await
208 }
209
210 pub async fn due_timed_expiry(
212 &self,
213 limit: i64,
214 ) -> super::RepositoryResult<Vec<super::TimedExpiryCandidate>> {
215 self.repository.due_timed_expiry(self.at, limit).await
216 }
217
218 pub async fn expire_due_timed(&self, limit: i64) -> super::RepositoryResult<u64> {
220 self.repository.expire_due_timed(self.at, limit).await
221 }
222
223 #[cfg(feature = "fulfillment-counters")]
225 pub async fn fulfillment_snapshot(
226 &self,
227 keepsake_id: Uuid,
228 ) -> super::RepositoryResult<keepsake::FulfillmentSnapshot> {
229 self.repository.fulfillment_snapshot(keepsake_id).await
230 }
231
232 #[cfg(feature = "fulfillment-counters")]
234 pub async fn due_fulfilled_expiry(
235 &self,
236 limit: i64,
237 ) -> super::RepositoryResult<Vec<FulfilledExpiryCandidate>> {
238 self.repository.due_fulfilled_expiry(limit).await
239 }
240
241 #[cfg(feature = "fulfillment-counters")]
243 pub async fn expire_due_fulfilled(&self, limit: i64) -> super::RepositoryResult<u64> {
244 self.repository.expire_due_fulfilled(self.at, limit).await
245 }
246
247 #[cfg(feature = "fulfillment-counters")]
249 pub async fn upsert_counter_projection(
250 &self,
251 keepsake_id: Uuid,
252 key: &str,
253 value: i64,
254 ) -> super::RepositoryResult<()> {
255 self.repository
256 .upsert_counter_projection(keepsake_id, key, value, self.at)
257 .await
258 }
259
260 #[cfg(feature = "fulfillment-counters")]
262 pub async fn increment_counter_projection(
263 &self,
264 keepsake_id: Uuid,
265 key: &str,
266 delta: i64,
267 ) -> super::RepositoryResult<i64> {
268 self.repository
269 .increment_counter_projection(keepsake_id, key, delta, self.at)
270 .await
271 }
272
273 #[cfg(feature = "fulfillment-counters")]
275 pub async fn upsert_checklist_projection(
276 &self,
277 keepsake_id: Uuid,
278 item: &str,
279 complete: bool,
280 ) -> super::RepositoryResult<()> {
281 self.repository
282 .upsert_checklist_projection(keepsake_id, item, complete, self.at)
283 .await
284 }
285}
286
287#[cfg(feature = "mysql")]
288impl<C> TimedMySqlKeepsakeRepository<'_, C>
289where
290 C: super::RelationCache,
291{
292 pub async fn upsert_relation(
294 &self,
295 relation: &RelationDefinition,
296 ) -> super::RepositoryResult<RelationDefinition> {
297 self.repository.upsert_relation(relation, self.at).await
298 }
299
300 pub async fn upsert_relation_spec<Spec>(&self) -> super::RepositoryResult<RelationDefinition>
302 where
303 Spec: RelationSpec,
304 {
305 self.repository.upsert_relation_spec::<Spec>(self.at).await
306 }
307
308 pub async fn set_relation_enabled(
310 &self,
311 relation_id: RelationId,
312 enabled: bool,
313 ) -> super::RepositoryResult<bool> {
314 self.repository
315 .set_relation_enabled(relation_id, enabled, self.at)
316 .await
317 }
318
319 pub async fn due_timed_expiry(
321 &self,
322 limit: i64,
323 ) -> super::RepositoryResult<Vec<super::TimedExpiryCandidate>> {
324 self.repository.due_timed_expiry(self.at, limit).await
325 }
326
327 pub async fn expire_due_timed(&self, limit: i64) -> super::RepositoryResult<u64> {
329 self.repository.expire_due_timed(self.at, limit).await
330 }
331
332 #[cfg(feature = "fulfillment-counters")]
334 pub async fn fulfillment_snapshot(
335 &self,
336 keepsake_id: Uuid,
337 ) -> super::RepositoryResult<keepsake::FulfillmentSnapshot> {
338 self.repository.fulfillment_snapshot(keepsake_id).await
339 }
340
341 #[cfg(feature = "fulfillment-counters")]
343 pub async fn due_fulfilled_expiry(
344 &self,
345 limit: i64,
346 ) -> super::RepositoryResult<Vec<FulfilledExpiryCandidate>> {
347 self.repository.due_fulfilled_expiry(limit).await
348 }
349
350 #[cfg(feature = "fulfillment-counters")]
352 pub async fn expire_due_fulfilled(&self, limit: i64) -> super::RepositoryResult<u64> {
353 self.repository.expire_due_fulfilled(self.at, limit).await
354 }
355
356 #[cfg(feature = "fulfillment-counters")]
358 pub async fn upsert_counter_projection(
359 &self,
360 keepsake_id: Uuid,
361 key: &str,
362 value: i64,
363 ) -> super::RepositoryResult<()> {
364 self.repository
365 .upsert_counter_projection(keepsake_id, key, value, self.at)
366 .await
367 }
368
369 #[cfg(feature = "fulfillment-counters")]
371 pub async fn increment_counter_projection(
372 &self,
373 keepsake_id: Uuid,
374 key: &str,
375 delta: i64,
376 ) -> super::RepositoryResult<i64> {
377 self.repository
378 .increment_counter_projection(keepsake_id, key, delta, self.at)
379 .await
380 }
381
382 #[cfg(feature = "fulfillment-counters")]
384 pub async fn upsert_checklist_projection(
385 &self,
386 keepsake_id: Uuid,
387 item: &str,
388 complete: bool,
389 ) -> super::RepositoryResult<()> {
390 self.repository
391 .upsert_checklist_projection(keepsake_id, item, complete, self.at)
392 .await
393 }
394}