a3s-flow 1.1.0

Durable workflow engine and Rust SDK for A3S
Documentation
use std::sync::Arc;

use a3s_flow::{
    FlowEngine, FlowRuntime, RuntimeCommand, StepInvocation, WorkflowInvocation, WorkflowRunStatus,
    WorkflowSpec,
};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

#[derive(Debug, Clone, Serialize, Deserialize)]
struct SegmentInput {
    cursor: u64,
    total: u64,
}

struct SegmentedImport;

#[async_trait]
impl FlowRuntime for SegmentedImport {
    async fn run_workflow(
        &self,
        invocation: WorkflowInvocation,
    ) -> a3s_flow::Result<RuntimeCommand> {
        let context = invocation.context();
        let input: SegmentInput = context.input_as()?;
        if input.cursor < input.total {
            return Ok(context.continue_as_new(json!(SegmentInput {
                cursor: input.cursor + 1,
                total: input.total,
            })));
        }
        Ok(context.complete(json!({ "processed": input.total })))
    }

    async fn run_step(&self, _invocation: StepInvocation) -> a3s_flow::Result<Value> {
        unreachable!("this history-segmentation example has no side-effecting steps")
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> a3s_flow::Result<()> {
    let engine = FlowEngine::in_memory(Arc::new(SegmentedImport));
    let spec = WorkflowSpec::rust_embedded(
        "examples.segmented-import",
        "1",
        "examples::continue_as_new",
        "main",
    );

    let root_run_id = engine
        .start_with_id(
            "segmented-import",
            spec,
            json!(SegmentInput {
                cursor: 0,
                total: 3,
            }),
        )
        .await?;
    let chain = engine.continuation_chain(&root_run_id).await?;

    for snapshot in &chain {
        println!(
            "run={} status={:?} events={}",
            snapshot.run_id,
            snapshot.status,
            engine.history(&snapshot.run_id).await?.len()
        );
    }
    assert_eq!(chain.len(), 4);
    assert_eq!(chain.last().unwrap().status, WorkflowRunStatus::Completed);
    Ok(())
}