Skip to content

FoundatioFx/Jint.Workflows

Repository files navigation

Jint.Workflows

FoundatioFoundatio

Build status NuGet Version feedz.io Discord

Durable JavaScript workflows for .NET using Jint. Write long-running orchestration logic as async JavaScript, suspend execution at any await, serialize the state, and resume later — potentially days later, in a different process. Uses deterministic replay on top of Jint's public API, with zero engine modifications.

Influenced by Vercel's Workflow SDK, adapted for the .NET / Jint environment.

✨ Features

  • 💾 Tiny, portable state — serialized state is a compact JSON journal of results; store it anywhere
  • Suspend for days — pause at any await, persist, resume in a different process
  • 🔁 Deterministic replayDate.now(), new Date(), Math.random() overridden for stable replays
  • 🛡️ Journaled side effects — step functions execute once and replay from cache
  • 🩹 Policy-based retries — attach Foundatio.Resilience policies for in-process retry, or throw RetryableStepException for durable cross-restart retries
  • 🌐 Browser-compatible fetch — opt-in WHATWG fetch with .json(), .text(), .clone()
  • 📣 Named external eventswaitForEvent('name') single or multi-event, with timeout support
  • 🔀 Fan-out/fan-inPromise.all and Promise.race over steps and suspends
  • ♾️ Continue As New — restart with a fresh journal to avoid unbounded growth
  • 🛠️ Journal compatibility check — script drift fails fast with a clear diagnostic

🚀 Get Started

dotnet add package Jint.Workflows
using Jint.Workflows;

var workflow = new WorkflowEngine();
workflow.RegisterSuspendFunction("sleep", args => DurationParser.Parse(args[0]));
workflow.RegisterStepFunction("fetchOrder", args => orderService.GetOrder((string)args[0]!));
workflow.RegisterSuspendFunction("getApproval");

var script = """
    async function processOrder(orderId) {
        const order = await fetchOrder(orderId);
        await sleep('3d');
        const approved = await getApproval('manager', orderId);
        return approved ? 'shipped' : 'cancelled';
    }
""";

var result = workflow.RunWorkflow(script, "processOrder", "ORD-001");
// result.Status == Suspended, result.Suspension.ResumeAt ≈ 3 days from now

var json = result.State!.Serialize();  // persist anywhere

// ... 3 days later, in a different process
var resumed = workflow.ResumeWorkflow(script, json);

👉 Getting Started Guide — step-by-step setup, step functions, suspend functions, and replay.

📖 Complete Documentation

📦 CI Packages (Feedz)

Want the latest CI build before it hits NuGet? Add the Feedz source (read-only public) and install the pre-release version:

dotnet nuget add source https://f.feedz.io/foundatio/foundatio/nuget -n foundatio-feedz
dotnet add package Jint.Workflows --prerelease

Or add to your NuGet.config:

<configuration>
    <packageSources>
        <add key="foundatio-feedz" value="https://f.feedz.io/foundatio/foundatio/nuget" />
    </packageSources>
    <packageSourceMapping>
        <packageSource key="foundatio-feedz">
            <package pattern="Foundatio.*" />
            <package pattern="Jint.Workflows" />
        </packageSource>
    </packageSourceMapping>
</configuration>

🤝 Contributing

Contributions are welcome! See the documentation for how the engine works and what edits are safe across versions.

🔗 Related Projects

  • Jint — the JavaScript interpreter this library is built on
  • Vercel Workflow SDK — the primary source of inspiration for the replay-based durable workflow model
  • Azure Durable Functions — canonical .NET implementation of the deterministic replay pattern
  • Temporal / Restate — full workflow runtimes with the same replay model at a larger scope

📄 License

Apache-2.0 License

About

Durable JavaScript workflows for .NET using Jint. Suspend, serialize, and resume long-running orchestration with deterministic replay.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages