1use serde::{Deserialize, Serialize};
12use std::sync::Arc;
13use chrono;
14use backbone_core::flow::{WorkflowStep, WorkflowContext};
15
16#[derive(Debug, Clone, thiserror::Error)]
18pub enum FlowError {
19 #[error("No current step to execute")]
20 NoCurrentStep,
21
22 #[error("Step execution failed: {0}")]
23 StepFailed(String),
24
25 #[error("Condition evaluation failed: {0}")]
26 ConditionFailed(String),
27
28 #[error("Compensation failed: {0}")]
29 CompensationFailed(String),
30
31 #[error("Flow timed out")]
32 Timeout,
33
34 #[error("Flow cancelled")]
35 Cancelled,
36
37 #[error("Invalid state transition: {from} -> {to}")]
38 InvalidTransition { from: String, to: String },
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
43#[serde(rename_all = "snake_case")]
44pub enum ShareCreationFlowStatus {
45 Pending,
47 Running,
49 Waiting,
51 Completed,
53 Failed,
55 Cancelled,
57 Compensating,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
63#[serde(rename_all = "snake_case")]
64pub enum ShareCreationFlowStep {
65 ValidateFile,
67 CheckSharePermission,
69 CheckManagePermission,
71 CheckShareType,
73 ValidatePublicShare,
75 ValidateUserShare,
77 ValidateEmailShare,
79 CheckExistingShare,
81 UpdateExistingShare,
83 CreateShareRecord,
85 GenerateShareUrl,
87 DetermineNotification,
89 NotifyUser,
91 SendEmailInvitation,
93 LogShare,
95 Complete,
97 FileNotFound,
99 PermissionDenied,
101 FailedPermission,
103 PublicSharingDisabled,
105 UserNotFound,
107 InvalidConfig,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct ShareCreationFlowInstance {
114 pub id: String,
116 pub status: ShareCreationFlowStatus,
118 pub current_step: Option<ShareCreationFlowStep>,
120 pub context: serde_json::Value,
122 pub completed_steps: Vec<ShareCreationFlowStep>,
124 pub error: Option<String>,
126 pub created_at: chrono::DateTime<chrono::Utc>,
128 pub updated_at: chrono::DateTime<chrono::Utc>,
130}
131
132impl ShareCreationFlowInstance {
133 pub fn new(id: impl Into<String>) -> Self {
135 let now = chrono::Utc::now();
136 Self {
137 id: id.into(),
138 status: ShareCreationFlowStatus::Pending,
139 current_step: None,
140 context: serde_json::json!({}),
141 completed_steps: Vec::new(),
142 error: None,
143 created_at: now,
144 updated_at: now,
145 }
146 }
147
148 pub fn is_complete(&self) -> bool {
150 matches!(
151 self.status,
152 ShareCreationFlowStatus::Completed | ShareCreationFlowStatus::Failed | ShareCreationFlowStatus::Cancelled
153 )
154 }
155
156 pub fn is_running(&self) -> bool {
158 matches!(
159 self.status,
160 ShareCreationFlowStatus::Running | ShareCreationFlowStatus::Waiting
161 )
162 }
163
164 pub fn set_context(&mut self, key: &str, value: serde_json::Value) {
166 if let serde_json::Value::Object(ref mut map) = self.context {
167 map.insert(key.to_string(), value);
168 }
169 self.updated_at = chrono::Utc::now();
170 }
171
172 pub fn get_context(&self, key: &str) -> Option<&serde_json::Value> {
174 if let serde_json::Value::Object(ref map) = self.context {
175 map.get(key)
176 } else {
177 None
178 }
179 }
180}
181
182#[allow(unused_variables)]
186impl WorkflowContext<ShareCreationFlowInstance> for ShareCreationFlowInstance {
187 fn entity(&self) -> &ShareCreationFlowInstance { self }
188 fn set_var(&mut self, key: &str, value: serde_json::Value) {
189 self.set_context(key, value);
190 }
191 fn get_var(&self, key: &str) -> Option<&serde_json::Value> {
192 self.get_context(key)
193 }
194}
195
196#[async_trait::async_trait]
198pub trait ShareCreationStepHandler: Send + Sync {
199 async fn handle_validate_file(
201 &self,
202 instance: &mut ShareCreationFlowInstance,
203 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
204
205 async fn evaluate_check_share_permission(
207 &self,
208 instance: &ShareCreationFlowInstance,
209 ) -> Result<ShareCreationFlowStep, FlowError>;
210
211 async fn handle_check_manage_permission(
213 &self,
214 instance: &mut ShareCreationFlowInstance,
215 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
216
217 async fn evaluate_check_share_type(
219 &self,
220 instance: &ShareCreationFlowInstance,
221 ) -> Result<ShareCreationFlowStep, FlowError>;
222
223 async fn handle_validate_public_share(
225 &self,
226 instance: &mut ShareCreationFlowInstance,
227 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
228
229 async fn handle_validate_user_share(
231 &self,
232 instance: &mut ShareCreationFlowInstance,
233 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
234
235 async fn handle_validate_email_share(
237 &self,
238 instance: &mut ShareCreationFlowInstance,
239 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
240
241 async fn handle_check_existing_share(
243 &self,
244 instance: &mut ShareCreationFlowInstance,
245 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
246
247 async fn handle_update_existing_share(
249 &self,
250 instance: &mut ShareCreationFlowInstance,
251 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
252
253 async fn handle_create_share_record(
255 &self,
256 instance: &mut ShareCreationFlowInstance,
257 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
258
259 async fn handle_generate_share_url(
261 &self,
262 instance: &mut ShareCreationFlowInstance,
263 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
264
265 async fn evaluate_determine_notification(
267 &self,
268 instance: &ShareCreationFlowInstance,
269 ) -> Result<ShareCreationFlowStep, FlowError>;
270
271 async fn handle_notify_user(
273 &self,
274 instance: &mut ShareCreationFlowInstance,
275 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
276
277 async fn handle_send_email_invitation(
279 &self,
280 instance: &mut ShareCreationFlowInstance,
281 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
282
283 async fn handle_log_share(
285 &self,
286 instance: &mut ShareCreationFlowInstance,
287 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
288
289 async fn handle_complete(
291 &self,
292 instance: &mut ShareCreationFlowInstance,
293 ) -> Result<(), FlowError>;
294
295 async fn handle_file_not_found(
297 &self,
298 instance: &mut ShareCreationFlowInstance,
299 ) -> Result<(), FlowError>;
300
301 async fn handle_permission_denied(
303 &self,
304 instance: &mut ShareCreationFlowInstance,
305 ) -> Result<Option<ShareCreationFlowStep>, FlowError>;
306
307 async fn handle_failed_permission(
309 &self,
310 instance: &mut ShareCreationFlowInstance,
311 ) -> Result<(), FlowError>;
312
313 async fn handle_public_sharing_disabled(
315 &self,
316 instance: &mut ShareCreationFlowInstance,
317 ) -> Result<(), FlowError>;
318
319 async fn handle_user_not_found(
321 &self,
322 instance: &mut ShareCreationFlowInstance,
323 ) -> Result<(), FlowError>;
324
325 async fn handle_invalid_config(
327 &self,
328 instance: &mut ShareCreationFlowInstance,
329 ) -> Result<(), FlowError>;
330
331}
332
333pub struct ShareCreationFlowExecutor<H: ShareCreationStepHandler> {
335 handler: Arc<H>,
336}
337
338impl<H: ShareCreationStepHandler> ShareCreationFlowExecutor<H> {
339 pub fn new(handler: Arc<H>) -> Self {
341 Self { handler }
342 }
343
344 pub async fn start(&self, instance_id: impl Into<String>) -> Result<ShareCreationFlowInstance, FlowError> {
346 let mut instance = ShareCreationFlowInstance::new(instance_id);
347 instance.status = ShareCreationFlowStatus::Running;
348 instance.current_step = Some(ShareCreationFlowStep::ValidateFile);
349 Ok(instance)
350 }
351
352 pub async fn execute_step(&self, instance: &mut ShareCreationFlowInstance) -> Result<(), FlowError> {
354 let current_step = match instance.current_step {
355 Some(step) => step,
356 None => return Err(FlowError::NoCurrentStep),
357 };
358
359 let next_step = match current_step {
360 ShareCreationFlowStep::ValidateFile => {
361 self.handler.handle_validate_file(instance).await?
362 }
363 ShareCreationFlowStep::CheckSharePermission => {
364 let next = self.handler.evaluate_check_share_permission(instance).await?;
365 Some(next)
366 }
367 ShareCreationFlowStep::CheckManagePermission => {
368 self.handler.handle_check_manage_permission(instance).await?
369 }
370 ShareCreationFlowStep::CheckShareType => {
371 let next = self.handler.evaluate_check_share_type(instance).await?;
372 Some(next)
373 }
374 ShareCreationFlowStep::ValidatePublicShare => {
375 self.handler.handle_validate_public_share(instance).await?
376 }
377 ShareCreationFlowStep::ValidateUserShare => {
378 self.handler.handle_validate_user_share(instance).await?
379 }
380 ShareCreationFlowStep::ValidateEmailShare => {
381 self.handler.handle_validate_email_share(instance).await?
382 }
383 ShareCreationFlowStep::CheckExistingShare => {
384 self.handler.handle_check_existing_share(instance).await?
385 }
386 ShareCreationFlowStep::UpdateExistingShare => {
387 self.handler.handle_update_existing_share(instance).await?
388 }
389 ShareCreationFlowStep::CreateShareRecord => {
390 self.handler.handle_create_share_record(instance).await?
391 }
392 ShareCreationFlowStep::GenerateShareUrl => {
393 self.handler.handle_generate_share_url(instance).await?
394 }
395 ShareCreationFlowStep::DetermineNotification => {
396 let next = self.handler.evaluate_determine_notification(instance).await?;
397 Some(next)
398 }
399 ShareCreationFlowStep::NotifyUser => {
400 self.handler.handle_notify_user(instance).await?
401 }
402 ShareCreationFlowStep::SendEmailInvitation => {
403 self.handler.handle_send_email_invitation(instance).await?
404 }
405 ShareCreationFlowStep::LogShare => {
406 self.handler.handle_log_share(instance).await?
407 }
408 ShareCreationFlowStep::Complete => {
409 self.handler.handle_complete(instance).await?;
410 None }
412 ShareCreationFlowStep::FileNotFound => {
413 self.handler.handle_file_not_found(instance).await?;
414 None }
416 ShareCreationFlowStep::PermissionDenied => {
417 self.handler.handle_permission_denied(instance).await?
418 }
419 ShareCreationFlowStep::FailedPermission => {
420 self.handler.handle_failed_permission(instance).await?;
421 None }
423 ShareCreationFlowStep::PublicSharingDisabled => {
424 self.handler.handle_public_sharing_disabled(instance).await?;
425 None }
427 ShareCreationFlowStep::UserNotFound => {
428 self.handler.handle_user_not_found(instance).await?;
429 None }
431 ShareCreationFlowStep::InvalidConfig => {
432 self.handler.handle_invalid_config(instance).await?;
433 None }
435 };
436
437 instance.completed_steps.push(current_step);
439
440 match next_step {
442 Some(next) => {
443 instance.current_step = Some(next);
444 }
445 None => {
446 instance.current_step = None;
447 instance.status = ShareCreationFlowStatus::Completed;
448 }
449 }
450
451 instance.updated_at = chrono::Utc::now();
452 Ok(())
453 }
454
455 pub async fn run(&self, instance: &mut ShareCreationFlowInstance) -> Result<(), FlowError> {
457 while !instance.is_complete() && instance.status != ShareCreationFlowStatus::Waiting {
458 self.execute_step(instance).await?;
459 }
460 Ok(())
461 }
462
463 pub fn cancel(&self, instance: &mut ShareCreationFlowInstance) {
465 instance.status = ShareCreationFlowStatus::Cancelled;
466 instance.updated_at = chrono::Utc::now();
467 }
468
469 pub fn fail(&self, instance: &mut ShareCreationFlowInstance, error: impl Into<String>) {
471 instance.status = ShareCreationFlowStatus::Failed;
472 instance.error = Some(error.into());
473 instance.updated_at = chrono::Utc::now();
474 }
475}
476
477#[cfg(test)]
478mod tests {
479 use super::*;
480
481 #[test]
482 fn test_flow_instance_creation() {
483 let instance = ShareCreationFlowInstance::new("test-1");
484 assert_eq!(instance.id, "test-1");
485 assert_eq!(instance.status, ShareCreationFlowStatus::Pending);
486 assert!(!instance.is_complete());
487 }
488
489 #[test]
490 fn test_flow_context() {
491 let mut instance = ShareCreationFlowInstance::new("test-2");
492 instance.set_context("key", serde_json::json!("value"));
493 let value = instance.get_context("key");
494 assert_eq!(value, Some(&serde_json::json!("value")));
495 }
496
497 #[test]
498 fn test_flow_status_transitions() {
499 let mut instance = ShareCreationFlowInstance::new("test-3");
500 assert!(!instance.is_running());
501
502 instance.status = ShareCreationFlowStatus::Running;
503 assert!(instance.is_running());
504 assert!(!instance.is_complete());
505
506 instance.status = ShareCreationFlowStatus::Completed;
507 assert!(instance.is_complete());
508 assert!(!instance.is_running());
509 }
510}