Rust workflow runtime that keeps inputs deterministic, timers reliable, and effects idempotent so you can orchestrate recurring jobs, polling, or automation with minimal overhead. Ironflow packages both the runtime crate (ironflow) and the helper macros (ironflow-macros), and exposes detailed architecture and usage guidance under crates/ironflow/docs/README.md.
NB: Ironflow is in active development and testing. Expect breaking changes, bugs, and potential concurrency or data issues in the current release and between releases; use in production only with caution.
Ironflow implements an event-sourced workflow engine with an async effect outbox, timers, and input observation tracking. The ironflow crate provides the core runtime plus Postgres-backed persistence, while ironflow-macros ships derive helpers such as HasWorkflowId so downstream crates can keep input handling concise. Refer to crates/ironflow/docs/README.md for a guided tour of the architecture, core workflow model, and practical how-tos.
-
Copy and adjust the configuration The repository ships
.env.examplewith:DATABASE_URL="postgres://postgres:postgres@localhost:5432/ironflow" TEST_ADMIN_DATABASE_URL="postgres://postgres:postgres@localhost:5432/postgres"
DATABASE_URLis used by SQLx for compile-time query checking and migration execution, so keep it pointed at the schema you want the runtime to use.TEST_ADMIN_DATABASE_URLis used by the integration tests to create and tear down per-test databases, so grant it permissions to create databases or adjust as needed for CI.cp .env.example .env # edit .env to match your setup (DATABASE_URL, other overlays, etc.) -
Run a local Postgres instance (for development)
./scripts/spin_up_docker_services.sh
The script brings up the Docker services and waits for Postgres to accept connections, using the same credentials as
.env.example. -
Prepare and migrate the database
Ironflow ships its schema insidecrates/ironflow/migrations/20251230000001_create_ironflow_schema.sql. Run SQLx against theDATABASE_URLdefined in your.envfile to create the database (if needed) and apply the migration../scripts/sqlx_migrate.sh
Downstream crates that depend on Ironflow should either run
cargo sqlx migrate run --source crates/ironflow/migrationsfrom this repository (if they vendor thecrates/ironflow/migrations/directory) or manually apply the named SQL file for the release they depend on (crates/ironflow/migrations/20251230000001_create_ironflow_schema.sql). Keeping migrations additive ensures each version exposes a clear upgrade path for consumers.
-
Add Ironflow as a dependency:
[dependencies] ironflow = { version = "0.1", features = ["postgres"] }
Enable the
postgresfeature to pull in SQLx/Postgres support and pair it withironflow-macroswhen you rely on derives such asHasWorkflowId.If you build without a database, set
SQLX_OFFLINE=trueand rely on the shipped.sqlx/metadata (generated viacargo sqlx prepare). -
Reuse the fixtures under
crates/ironflow/tests/postgres/for integration scenarios; the README in that directory explains each test group and supporting helper.
cargo install --locked bacon
cargo install --locked cargo-deny
# Unused dependency checker (requires nightly)
cargo install --locked cargo-udeps
# Install sqlx-cli with the repo-pinned version
./scripts/sqlx_install.sh
# Add, remove, and upgrade dependencies
cargo install --locked cargo-edit
# TOML formatting
cargo install --locked taplo-cli# SQL formatter (pgFormatter):
npm install -g pgformatter
# Markdown formatter (Prettier):
npm install -g prettier@3.7.4# cargo upgrade is provided by `cargo-edit`
cargo upgrade --incompatible --dry-run
# Analyze above output and if happy:
cargo upgrade --incompatible
# Then update lockfile
cargo update
# Find unused deps (requires nightly)
cargo +nightly udeps --all-features# Update rustup and the default toolchain
rustup self update
rustup update
# If the repo pins a toolchain via rust-toolchain.toml, ensure it is installed
rustup showThese can be useful but are not required for day-to-day work:
shfmt -dif you want shell formatting enforcement
Recommended one-shot check:
./scripts/verify.shIndividual checks:
./scripts/format-sql.sh --check
./scripts/format-toml.sh --check
./scripts/format-md.sh --check
./scripts/security-check.sh
cargo check --workspace --all-targets --all-features
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warningscargo test --workspaceThe Postgres integration suite includes shared test helpers under crates/ironflow/tests/postgres/support/ for database isolation and environment variables.
Using the macro (recommended):
use crate::db_test;
db_test!(test_users, |pool| {
sqlx::query!("SELECT COUNT(*) FROM users")
.fetch_one(pool)
.await?;
Ok(())
});Force preservation for any test:
TEST_KEEP_DB=1 cargo test test_users- Create - Generates unique database:
test_{test_name}_{uuid_v7} - Migrate - Applies Unity migrations automatically
- Test - Runs your test code with connection pool
- Cleanup - On success: drops database | On failure: preserves for debugging
Read the design notes, workflow core, and how-to guides in crates/ironflow/docs/README.md. When contributing, keep schema migrations and docs synchronized with code changes so downstream dependents know which migration to apply for each release.