chronon_executor/
registry.rs1use std::collections::HashMap;
4
5use chronon_core::{ChrononError, Result};
6
7use crate::descriptor::{InvokeFn, ScriptDescriptor};
8
9struct StoredScript {
10 name: String,
11 invoke: InvokeFn,
12 signature_json: String,
13 signature_hash: u64,
14}
15
16pub struct ScriptRegistry {
21 scripts: HashMap<String, StoredScript>,
22}
23
24impl Default for ScriptRegistry {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl ScriptRegistry {
31 pub fn new() -> Self {
42 Self {
43 scripts: HashMap::new(),
44 }
45 }
46
47 pub fn from_inventory() -> Self {
49 let mut registry = Self::new();
50 registry.register_from_inventory();
51 registry
52 }
53
54 pub fn register_from_inventory(&mut self) {
56 for desc in quark::inventory::iter::<ScriptDescriptor> {
57 self.register(ScriptDescriptor::with_signature(
58 desc.name,
59 desc.invoke,
60 desc.signature_json,
61 desc.signature_hash,
62 ));
63 }
64 }
65
66 pub fn register(&mut self, desc: ScriptDescriptor) {
70 self.scripts.insert(
71 desc.name.to_string(),
72 StoredScript {
73 name: desc.name.to_string(),
74 invoke: desc.invoke,
75 signature_json: desc.signature_json.to_string(),
76 signature_hash: desc.signature_hash,
77 },
78 );
79 }
80
81 pub fn get(&self, name: &str) -> Option<ScriptDescriptorRef<'_>> {
83 self.scripts.get(name).map(|s| ScriptDescriptorRef {
84 name: s.name.as_str(),
85 invoke: s.invoke,
86 signature_json: s.signature_json.as_str(),
87 signature_hash: s.signature_hash,
88 })
89 }
90
91 pub fn get_or_err(&self, name: &str) -> Result<ScriptDescriptorRef<'_>> {
93 self.get(name)
94 .ok_or_else(|| ChrononError::ScriptNotFound(name.to_string()))
95 }
96
97 pub fn len(&self) -> usize {
99 self.scripts.len()
100 }
101
102 pub fn is_empty(&self) -> bool {
104 self.scripts.is_empty()
105 }
106
107 pub fn contains(&self, name: &str) -> bool {
109 self.scripts.contains_key(name)
110 }
111
112 pub fn list(&self) -> Vec<ScriptDescriptorRef<'_>> {
114 let mut v: Vec<_> = self.scripts.values().map(stored_to_ref).collect();
115 v.sort_by_key(|d| d.name);
116 v
117 }
118}
119
120#[derive(Clone, Copy)]
122pub struct ScriptDescriptorRef<'a> {
123 pub name: &'a str,
125 pub invoke: InvokeFn,
127 pub signature_json: &'a str,
129 pub signature_hash: u64,
131}
132
133fn stored_to_ref(s: &StoredScript) -> ScriptDescriptorRef<'_> {
134 ScriptDescriptorRef {
135 name: s.name.as_str(),
136 invoke: s.invoke,
137 signature_json: s.signature_json.as_str(),
138 signature_hash: s.signature_hash,
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145 use crate::descriptor::ScriptDescriptor;
146 use chronon_core::{Result, ScriptContext};
147 use serde_json::Value;
148 use std::future::Future;
149 use std::pin::Pin;
150
151 fn stub_invoke(
152 _ctx: Box<dyn ScriptContext>,
153 _params: Value,
154 ) -> Pin<Box<dyn Future<Output = Result<()>> + Send>> {
155 Box::pin(async { Ok(()) })
156 }
157
158 #[test]
159 fn register_and_lookup() {
160 let mut reg = ScriptRegistry::new();
161 reg.register(ScriptDescriptor::new("hello", stub_invoke));
162 assert!(reg.contains("hello"));
163 assert_eq!(reg.len(), 1);
164 }
165}