1use serde::{Deserialize, Serialize};
6
7pub trait ExtensionContext: Send + Sync {
9 fn extension_id(&self) -> &str;
11
12 fn version(&self) -> &str;
14
15 fn publisher(&self) -> &str;
17
18 fn display_name(&self) -> &str;
20
21 fn description(&self) -> &str;
23
24 fn is_development(&self) -> bool;
26}
27
28pub trait ExtensionMetadata: Send + Sync {
30 fn name(&self) -> &str;
32
33 fn publisher(&self) -> &str;
35
36 fn version(&self) -> &str;
38
39 fn description(&self) -> &str;
41
42 fn main(&self) -> &str;
44
45 fn activation_events(&self) -> &[String];
47
48 fn capabilities(&self) -> &[String];
50
51 fn dependencies(&self) -> &[String];
53
54 fn engine(&self) -> &str;
56}
57
58pub type GroveResult<T> = Result<T, GroveError>;
60
61#[derive(Debug, thiserror::Error)]
63pub enum GroveError {
64 #[error("Extension not found: {0}")]
66 ExtensionNotFound(String),
67
68 #[error("Extension activation failed: {0}")]
70 ActivationFailed(String),
71
72 #[error("Extension deactivation failed: {0}")]
74 DeactivationFailed(String),
75
76 #[error("Transport error: {0}")]
78 TransportError(String),
79
80 #[error("WASM runtime error: {0}")]
82 WASMError(String),
83
84 #[error("API error: {0}")]
86 APIError(String),
87
88 #[error("Configuration error: {0}")]
90 ConfigurationError(String),
91
92 #[error("I/O error: {0}")]
94 IoError(#[from] std::io::Error),
95
96 #[error("Serialization error: {0}")]
98 SerializationError(String),
99
100 #[error("Deserialization error: {0}")]
102 DeserializationError(String),
103
104 #[error("Operation timed out")]
106 Timeout,
107
108 #[error("Invalid argument: {0}")]
110 InvalidArgument(String),
111
112 #[error("Not implemented: {0}")]
114 NotImplemented(String),
115
116 #[error("{0}")]
118 Other(String),
119}
120
121pub trait Identifiable {
123 fn id(&self) -> &str;
125}
126
127pub trait Named {
129 fn name(&self) -> &str;
131}
132
133pub trait Configurable {
135 type Config;
137
138 fn configure(&mut self, config:Self::Config) -> anyhow::Result<()>;
140
141 fn config(&self) -> &Self::Config;
143}
144
145pub trait Resettable {
147 fn reset(&mut self) -> anyhow::Result<()>;
149}
150
151pub trait Disposable {
153 fn dispose(&mut self) -> anyhow::Result<()>;
155}
156
157pub trait ContextClone {
159 fn clone_with_context(&self, context:&serde_json::Value) -> anyhow::Result<Self>
161 where
162 Self: Sized;
163}
164
165pub trait Stateful {
167 type State: Clone;
169
170 fn state(&self) -> Self::State;
172
173 fn set_state(&mut self, state:Self::State) -> anyhow::Result<()>;
175
176 fn restore_state(&mut self, state:Self::State) -> anyhow::Result<()>;
178}
179
180pub trait Observable {
182 type Event;
184
185 fn subscribe(&self, callback:fn(Self::Event)) -> anyhow::Result<()>;
187
188 fn unsubscribe(&self) -> anyhow::Result<()>;
190}
191
192pub trait Validatable {
194 fn validate(&self) -> anyhow::Result<()>;
196}
197
198pub trait Serializable: Serialize + for<'de> Deserialize<'de> {
200 fn to_json(&self) -> anyhow::Result<String> {
202 serde_json::to_string(self).map_err(|e| anyhow::anyhow!("Serialization failed: {}", e))
203 }
204
205 fn to_json_pretty(&self) -> anyhow::Result<String> {
207 serde_json::to_string_pretty(self).map_err(|e| anyhow::anyhow!("Serialization failed: {}", e))
208 }
209
210 fn from_json(json:&str) -> anyhow::Result<Self>
212 where
213 Self: Sized, {
214 serde_json::from_str(json).map_err(|e| anyhow::anyhow!("Deserialization failed: {}", e))
215 }
216}
217
218impl<T> Serializable for T where T: Serialize + for<'de> Deserialize<'de> {}
220
221pub trait Versioned {
223 fn version(&self) -> &str;
225
226 fn is_compatible_with(&self, other_version:&str) -> bool;
228}
229
230pub trait Retryable {
232 fn execute_with_retry<F, T, E>(&self, mut operation:F, max_retries:u32, delay_ms:u64) -> anyhow::Result<T>
234 where
235 F: FnMut() -> Result<T, E> + Send,
236 E: std::fmt::Display + Send + 'static,
237 T: Send, {
238 let mut last_error = None;
239
240 for attempt in 0..=max_retries {
241 match operation() {
242 Ok(result) => return Ok(result),
243
244 Err(e) => {
245 last_error = Some(e.to_string());
246
247 if attempt < max_retries {
248 std::thread::sleep(std::time::Duration::from_millis(delay_ms));
249 }
250 },
251 }
252 }
253
254 Err(anyhow::anyhow!(
255 "Operation failed after {} attempts: {}",
256 max_retries + 1,
257 last_error.unwrap_or_else(|| "Unknown error".to_string())
258 ))
259 }
260}
261
262#[cfg(test)]
263mod tests {
264
265 use super::*;
266
267 #[test]
268 fn test_grove_error_display() {
269 let err = GroveError::ExtensionNotFound("test.ext".to_string());
270
271 assert_eq!(err.to_string(), "Extension not found: test.ext");
272
273 let err = GroveError::Timeout;
274
275 assert_eq!(err.to_string(), "Operation timed out");
276 }
277
278 #[test]
279 fn test_serializable_trait() {
280 #[derive(Serialize, Deserialize, PartialEq, Debug)]
281 struct TestStruct {
282 value:i32,
283 }
284
285 let test = TestStruct { value:42 };
286
287 let json = test.to_json().unwrap();
288
289 let deserialized:TestStruct = TestStruct::from_json(&json).unwrap();
290
291 assert_eq!(test, deserialized);
292 }
293
294 #[test]
295 fn test_retryable_execute_with_retry() {
296 let retryable = RetryableTrait;
297
298 let mut attempt_count = 0;
299
300 let result = retryable.execute_with_retry(
301 || {
302 attempt_count += 1;
303 if attempt_count < 3 { Err("Not ready") } else { Ok("Success") }
304 },
305 5,
306 100,
307 );
308
309 assert!(result.is_ok());
310
311 assert_eq!(result.unwrap(), "Success");
312
313 assert_eq!(attempt_count, 3);
314 }
315}
316
317#[allow(dead_code)]
319struct RetryableTrait;
320
321impl Retryable for RetryableTrait {}