forge_runtime/cron/
registry.rs1use std::collections::HashMap;
2use std::future::Future;
3use std::pin::Pin;
4use std::sync::Arc;
5
6use forge_core::cron::{CronContext, CronInfo, ForgeCron};
7
8pub type BoxedCronHandler = Arc<
10 dyn Fn(&CronContext) -> Pin<Box<dyn Future<Output = forge_core::Result<()>> + Send + '_>>
11 + Send
12 + Sync,
13>;
14
15pub struct CronEntry {
17 pub info: CronInfo,
19 pub handler: BoxedCronHandler,
21}
22
23impl CronEntry {
24 pub fn new<C: ForgeCron>() -> Self {
26 Self {
27 info: C::info(),
28 handler: Arc::new(|ctx| C::execute(ctx)),
29 }
30 }
31}
32
33#[derive(Default)]
35pub struct CronRegistry {
36 crons: HashMap<String, CronEntry>,
37}
38
39impl CronRegistry {
40 pub fn new() -> Self {
42 Self {
43 crons: HashMap::new(),
44 }
45 }
46
47 pub fn register<C: ForgeCron>(&mut self) {
49 let entry = CronEntry::new::<C>();
50 self.crons.insert(entry.info.name.to_string(), entry);
51 }
52
53 pub fn get(&self, name: &str) -> Option<&CronEntry> {
55 self.crons.get(name)
56 }
57
58 pub fn list(&self) -> Vec<&CronEntry> {
60 self.crons.values().collect()
61 }
62
63 pub fn len(&self) -> usize {
65 self.crons.len()
66 }
67
68 pub fn is_empty(&self) -> bool {
70 self.crons.is_empty()
71 }
72
73 pub fn names(&self) -> Vec<&str> {
75 self.crons.keys().map(|s| s.as_str()).collect()
76 }
77}
78
79impl Clone for CronRegistry {
80 fn clone(&self) -> Self {
81 Self {
82 crons: self
83 .crons
84 .iter()
85 .map(|(k, v)| {
86 (
87 k.clone(),
88 CronEntry {
89 info: v.info.clone(),
90 handler: v.handler.clone(),
91 },
92 )
93 })
94 .collect(),
95 }
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_empty_registry() {
105 let registry = CronRegistry::new();
106 assert!(registry.is_empty());
107 assert_eq!(registry.len(), 0);
108 }
109}