{"id":50682568,"url":"https://github.com/melonask/bria","last_synced_at":"2026-06-08T20:01:06.897Z","repository":{"id":363389071,"uuid":"1262457650","full_name":"melonask/bria","owner":"melonask","description":"Bria is a Rust-based multi-pipeline job orchestrator. It ingests jobs from files, HTTP/webhooks, AMQP, cron, PostgreSQL, or SQLite, runs local, Docker, or WebAssembly tasks; and emits results to files, webhooks, AMQP, databases, or live streams.","archived":false,"fork":false,"pushed_at":"2026-06-08T18:57:57.000Z","size":190,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T19:04:31.830Z","etag":null,"topics":["amqp","bria","jobs","ochestration","pipeline","postgresql","rust","sqlite","tasks"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/bria","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/melonask.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-08T02:23:39.000Z","updated_at":"2026-06-08T18:57:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/melonask/bria","commit_stats":null,"previous_names":["melonask/bria"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/melonask/bria","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melonask%2Fbria","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melonask%2Fbria/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melonask%2Fbria/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melonask%2Fbria/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/melonask","download_url":"https://codeload.github.com/melonask/bria/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melonask%2Fbria/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34078019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amqp","bria","jobs","ochestration","pipeline","postgresql","rust","sqlite","tasks"],"created_at":"2026-06-08T20:00:46.068Z","updated_at":"2026-06-08T20:01:06.889Z","avatar_url":"https://github.com/melonask.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bria\n\n\u003cimg align=\"right\" src=\"https://raw.githubusercontent.com/melonask/bria/refs/heads/main/logo.svg\" alt=\"Bria is a Rust-based multi-pipeline job orchestrator\" width=\"160\" /\u003e\n\n\u003e **Briareus** — One Command. Hundred Actions.\n\nBria is a Rust-based multi-pipeline job orchestrator. It ingests jobs from files, HTTP/webhooks, AMQP, cron, PostgreSQL, or SQLite, runs local, Docker, or WebAssembly tasks, and emits results to files, webhooks, AMQP, databases, or live streams.\n\n## Quick start\n\n```bash\ncargo install bria\n```\n\n```bash\nbria --config Config.toml\n```\n\n## CLI\n\n| Command | Description |\n|---|---|\n| `bria --config Config.toml` | Validate configuration and run Bria. |\n| `bria ping` | Print `pong`. |\n\n`--config` can also be supplied with `BRIA_CONFIG`. The default is `Config.toml`.\n\n## Configuration model\n\n| Section | Purpose |\n|---|---|\n| `[global]` | Runtime, logging, state, retry, and timeout defaults. |\n| `[server]` | Optional HTTP control plane for HTTP/webhook sources and streams. |\n| `[[sources]]` | Inputs that produce jobs. |\n| `[[tasks]]` | Reusable task definitions. |\n| `[[sinks]]` | Outputs that receive pipeline results. |\n| `[[pipelines]]` | DAGs connecting sources, tasks, and sinks. |\n\nEnvironment variables in the form `${VAR_NAME}` are resolved during config loading. Missing variables fail fast.\n\n## Parameters\n\n### Global\n\n| Key | Default | Description |\n|---|---:|---|\n| `worker_threads` | `0` | Tokio worker threads; `0` uses logical CPUs. |\n| `shutdown_timeout_secs` | `30` | Orchestrator shutdown timeout. |\n| `tmp_dir` | OS temp dir | Temporary file directory. |\n| `max_payload_bytes` | `10485760` | Maximum job payload size. |\n| `cancel_signal_ttl_secs` | `3600` | How long cancellation signals are retained. |\n\n### Logging: `[global.log]`\n\n| Key | Default | Values |\n|---|---|---|\n| `level` | `info` | `trace`, `debug`, `info`, `warn`, `error` |\n| `format` | auto | `text`, `json`; auto uses text on TTY and JSON otherwise |\n| `file` | `\"\"` | Optional log file path |\n\n### State: `[global.state]`\n\n| Key | Default | Description |\n|---|---|---|\n| `backend` | `memory` | `memory`, `sqlite`, or `pg`. |\n| `sqlite_path` | `bria-state.db` | SQLite state database. |\n| `pg_url` | `\"\"` | Required when `backend = \"pg\"`. |\n\nState stores queued/running job records for restart recovery. Schema is created automatically on first use.\n\n### Retry and timeout defaults\n\n| Section | Keys |\n|---|---|\n| `[global.retry]` | `max_attempts`, `base_delay_ms`, `max_delay_ms`, `jitter` |\n| `[global.timeout]` | `step_secs`, `action` (`kill`/`term`), `kill_grace_secs` |\n\nRetry precedence: step \u003e task \u003e global. Backoff uses exponential delay and random jitter.\n\n### Server: `[server]`\n\n| Key | Default | Description |\n|---|---:|---|\n| `enabled` | `false` | Enable HTTP server. |\n| `bind` | `0.0.0.0` | Bind address. |\n| `port` | `4000` | Listen port. |\n| `prefix` | `v1` | Route prefix. |\n| `api_key` | `\"\"` | Optional API key for all routes. Use `Authorization: Bearer` or `X-Bria-Api-Key`. |\n| `dashboard` | `\"\"` | Static dashboard directory. |\n| `shutdown_timeout_secs` | `5` | HTTP drain timeout. |\n| `max_body_bytes` | `52428800` | Server-wide body limit. |\n\nRoutes: `GET /{prefix}/ping`, `POST /{prefix}/{source.path}`, `DELETE /{prefix}/{source.path}/{job_id}`, `POST /{prefix}/pipelines/{id}/resume`, plus configured SSE/WebSocket stream paths.\n\n### Sources\n\n| Type | Required | Important parameters |\n|---|---|---|\n| `file` | `path` | `poll_interval_secs`, `track_cursor`, `authoritative`, `id_field`, `max_body_bytes`, `labels` |\n| `http` | `path`, `server.enabled=true` | `max_body_bytes`, `id_field`, `labels` |\n| `webhook` | `path`, `server.enabled=true` | `hmac_secret`, `hmac_header`, `ack_status`, `max_body_bytes` |\n| `queue` | `url`, `exchange` | `username`, `password`, `submit_routing_key`, `cancel_routing_key`, `reconnect_secs`, `qos_prefetch`, `consumer_tag` |\n| `cron` | `schedule` | `tz`, `[sources.payload]`, `labels` |\n| `pg` | `url`, `[sources.table]` | `poll_interval_secs`, table column names/status values |\n| `sqlite` | `path`, `[sources.table]` | same table parameters as `pg` |\n\nTable source columns: `id`, `payload`, `created_at`, `status`, `status_claimed_value`, `status_done_value`, `status_failed_value`.\n\n### Tasks\n\n| Key | Default | Description |\n|---|---|---|\n| `id` | required | Task identifier. |\n| `driver` | `local` | `local`, `docker`, or `wasm`. |\n| `cmd` | required | Command, image, or `.wasm` path. Supports templates. |\n| `args` | `[]` | Argument templates. |\n| `inherit_env` | `false` | Keep parent environment. |\n| `working_dir` | current dir | Child working directory. |\n| `success_exit_codes` | `[0]` | Successful exit codes. |\n| `timeout_secs` | global | Per-task timeout. |\n| `timeout_action` | global | `kill` or `term`. |\n| `kill_grace_secs` | global | Grace after SIGTERM. |\n| `[tasks.env]` | `{}` | Environment variables/templates. |\n| `[tasks.stdin]` | `mode=\"none\"` | `none`, `payload`, or `template`. |\n| `[tasks.stdout]` / `[tasks.stderr]` | `capture` | `mode`: `capture`, `stream`, `discard`; `max_bytes`. |\n| `[tasks.retry]` | global | Retry overrides. |\n\nDriver-specific sections:\n\n| Section | Keys |\n|---|---|\n| `[tasks.docker]` | `flags`, `mounts`, `pull` (`always`, `missing`, `never`) |\n| `[tasks.wasm]` | `dirs`, `max_memory_pages`, `fuel` |\n\n### Sinks\n\n| Type | Required | Parameters |\n|---|---|---|\n| `file` | `path` | `template` |\n| `webhook` | `url` | `secret`, `signature_header`, `content_type`, `max_retries`, `retry_base_ms`, `timeout_secs`, `headers` |\n| `queue` | `url`, `exchange` | `username`, `password`, `success_routing_key`, `failure_routing_key`, `reconnect_secs` |\n| `pg` | `url`, `[sinks.table]` | Result table and column names |\n| `sqlite` | `path`, `[sinks.table]` | Result table and column names |\n| `stream` | `server.enabled=true` | `sse`, `websocket`, `ws_heartbeat_secs`, `sse_keepalive_secs`, `broadcast_capacity` |\n\nTable sink columns: `result_id`, `job_id`, `pipeline_id`, `step_id`, `occurred_at`, `exit_code`, `stdout`, `stderr`, `duration_ms`, `attempt`, `status`.\n\n### Pipelines and steps\n\n| Key | Description |\n|---|---|\n| `id` | Pipeline identifier. |\n| `source` | Single source id. |\n| `sources` | Multiple source entries for merge pipelines. |\n| `[pipelines.merge]` | `strategy` (`any`/`all`), `correlation_key` or `correlation_expr`, `timeout_secs`. |\n| `concurrency` | Maximum concurrent steps/jobs. |\n| `queue_capacity` | Bounded channel size. |\n| `sinks` | Pipeline-level sinks. |\n| `[pipelines.failure]` | `action` (`discard`, `dead_letter`, `stop`) and optional `sink`. |\n| `labels` | Labels merged into jobs. |\n\nStep types:\n\n| Type | Required | Behavior |\n|---|---|---|\n| `process` | `task` | Runs a task. |\n| `map` | `[[pipelines.steps.set]]` | Mutates `job.payload` using CEL expressions. |\n| `condition` | `expr` | On false, `action = \"fail\"`, `\"skip_to\"`, or `\"emit\"`. |\n\nStep parameters include `depends_on`, `[with]` overrides, `[outputs]`, `[retry]`, `[failure]`, `sinks`, and `[[routing]]` conditional sinks.\n\n## Templates and expressions\n\nTemplates use MiniJinja and can access `job.*`, `steps.*`, `env.*`, `now`, `now_unix`, `pipeline.*`, `result.*`, and `occurred_at` depending on context.\n\nCEL expressions can read `job.*`, `steps.*`, and `pipeline.*`:\n\n```toml\n[[pipelines.steps.set]]\ntarget = \"job.payload.output_url\"\nexpr = '\"s3://\" + job.payload.bucket + \"/\" + job.payload.key'\n```\n\n## Example: HTTP job to local task and file sink\n\n```toml\n[server]\nenabled = true\nport = 4000\n\n[[sources]]\nid = \"api\"\ntype = \"http\"\npath = \"jobs\"\nid_field = \"id\"\n\n[[tasks]]\nid = \"hello\"\ndriver = \"local\"\ncmd = \"sh\"\nargs = [\"-c\", \"printf '{\\\"message\\\":\\\"hello %s\\\"}' \\\"$1\\\"\", \"sh\", \"{{job.payload.name}}\"]\n\n[[sinks]]\nid = \"results\"\ntype = \"file\"\npath = \"results.jsonl\"\n\n[[pipelines]]\nid = \"hello-pipeline\"\nsource = \"api\"\nsinks = [\"results\"]\n\n[[pipelines.steps]]\nid = \"run\"\ntype = \"process\"\ntask = \"hello\"\n```\n\nSend a job:\n\n```bash\ncurl -X POST http://localhost:4000/v1/jobs \\\n  -H 'content-type: application/json' \\\n  -d '{\"id\":\"job-1\",\"name\":\"Bria\"}'\n```\n\n## Docker\n\n```bash\ndocker run --rm -p 4000:4000 \\\n  -v \"$PWD/Config.toml:/etc/bria/Config.toml:ro\" \\\n  ghcr.io/melonask/bria:latest\n```\n\nThe default `CMD` passes `--config /etc/bria/Config.toml`.  Override it to run a\none-shot check or the built-in health command:\n\n```bash\ndocker run --rm bria:latest ping          # always works, no config needed\n```\n\nThe image includes an OCI `HEALTHCHECK` that calls `bria ping` every 30 s.\n\nE2E Docker Compose files and run script live in `tests/e2e/` — see `tests/e2e/README.md`.\n\n## Developer functions and exported API\n\n| Item | Purpose |\n|---|---|\n| `Config::load_from_path` | Load TOML with environment substitution. |\n| `Config::from_str_with_env` | Parse TOML string with `${VAR}` expansion. |\n| `Config::validate` | Validate references and type-specific requirements. |\n| `Config::get_task`, `Config::get_sink` | Lookup helpers. |\n| `Orchestrator::new` | Initialize logging and state store. |\n| `Orchestrator::run` | Start sources, server, routers, workers, and sinks. |\n| `run_pipeline_once` | Execute one pipeline in tests or embedded use. |\n| `create_store` | Create memory/SQLite/PostgreSQL state store. |\n| `StateStore` | Trait for queued/running/completed state and recovery. |\n\n## Testing\n\n```bash\n# Lint and unit/integration tests\ncargo fmt --check\ncargo clippy --all-targets --all-features -- -D warnings\ncargo test\n\n# End-to-end scenarios (requires Docker)\ncd tests/e2e\n./run.sh --all                    # build, run all 19 scenarios (~6 min), tear down\n./run.sh --infra-up               # start shared infra (postgres, rabbitmq, etc.)\n./run.sh http-pg                  # run a single scenario\n./run.sh --infra-down             # tear down shared infra\n# See tests/e2e/README.md for the full scenario list and architecture\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelonask%2Fbria","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmelonask%2Fbria","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelonask%2Fbria/lists"}