{"id":27078738,"url":"https://github.com/mu-box/qwit","last_synced_at":"2025-07-03T12:06:11.873Z","repository":{"id":57538926,"uuid":"376386245","full_name":"mu-box/qwit","owner":"mu-box","description":"A library for building workflows out of queued worker jobs, and running them as transactions.","archived":false,"fork":false,"pushed_at":"2023-06-18T16:14:27.000Z","size":22,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-09T14:49:29.759Z","etag":null,"topics":["elixir"],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mu-box.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-06-12T21:24:33.000Z","updated_at":"2024-05-19T17:27:17.000Z","dependencies_parsed_at":"2022-09-19T07:31:00.066Z","dependency_job_id":"b1f4aca4-1ebd-443f-8c7f-f997d31b7d59","html_url":"https://github.com/mu-box/qwit","commit_stats":{"total_commits":6,"total_committers":2,"mean_commits":3.0,"dds":"0.16666666666666663","last_synced_commit":"5dc96ad10d643a8dd6a939463d0f0827f2f3cf76"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mu-box/qwit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mu-box%2Fqwit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mu-box%2Fqwit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mu-box%2Fqwit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mu-box%2Fqwit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mu-box","download_url":"https://codeload.github.com/mu-box/qwit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mu-box%2Fqwit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260019148,"owners_count":22946531,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["elixir"],"created_at":"2025-04-06T01:17:46.613Z","updated_at":"2025-07-03T12:06:11.815Z","avatar_url":"https://github.com/mu-box.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Queued Workflows In Transactions\n\n![GitHub Workflow Status](https://img.shields.io/github/workflow/status/mu-box/qwit/Elixir%20CI)\n![Hex.pm](https://img.shields.io/hexpm/l/qwit)\n![Hex.pm](https://img.shields.io/hexpm/v/qwit)\n![Hex.pm](https://img.shields.io/hexpm/dt/qwit)\n![Discord](https://img.shields.io/discord/610589644651888651)\n![GitHub Sponsors](https://img.shields.io/github/sponsors/mu-box)\n\nMicrobox QWIT is a library for building workflows out of queued worker jobs, and\nrunning them as transactions. When errors happen, the entire workflow gets\nrewound, exactly like a failed database transaction.\n\nBuilt originally with support only for Oban, the intent is to support other\nqueued worker libraries in the future, so you can drop QWIT in with whatever\nqueue engine your project needs and get all the same benefits.\n\nDon't need a full queue engine? Check out\n[recipe](https://github.com/cloud8421/recipe) instead!\n\n## Why?\n\nMicrobox Core performs tasks that need to be reversible in case of failures.\nSince this portion of the project is so reusable elsewhere, it made sense to\nextract it into its own package. While Core uses Oban to improve scalability, it\nmakes sense to support as many queue engines as possible for maximum\nflexibility, so that's how we approach the architecture.\n\n## Installation\n\nAdd QWIT to your `mix.exs` with your other `deps`:\n\n```elixir\n{:qwit, \"~\u003e 0.1.0\"},\n```\n\nThen, as usual, `mix deps.get` and you'll be set! Nothing to configure, here.\n\n## Usage\n\nQWIT provides a common interface to all supported queue engines. That means all\nyou have to do is swap out your engine, update your modules, and everything else\nworks as before. You can even use multiple engines at once, since the\nappropriate engine is passed as a `use` option.\n\nWorkflows are provided by two module types - Flows and Steps. Flows dictate\nwhich steps are run in which order.\n\n\u003c!-- TODO: Come up with a more useful example here... --\u003e\n\n```elixir\ndefmodule MyApp.Work.Flows.Example do\n  use QWIT.Flow\n\n  @impl QWIT.Flow\n  def build_flow do\n    step MyApp.Work.Steps.Example, %{arg1: \"value1\"}\n    step MyApp.Work.Steps.Example\n  end\nend\n```\n\nSteps do the actual work, with the return values of each serving as additional\narguments to the next.\n\n```elixir\ndefmodule MyApp.Work.Steps.Example\n  use QWIT.Step\n\n  import Logger\n\n  @impl QWIT.Step\n  def step_forward(%{arg1: arg1}) do\n    Logger.info(\"Got first arg: #{arg1}\")\n\n    {:ok, %{arg2: \"value2\"}} # pass arg2 to following steps in flow\n  end\n  def step_forward(%{arg2: arg2}) do\n    Logger.info(\"Got second arg: #{arg2}\")\n  end\n\n  @impl QWIT.Step\n  def step_back(%{} = _args) do\n    Logger.info(\"Something went horribly wrong...\")\n  end\nend\n```\n\nFor especially complex workflows, you can call sub-Flows as though they were\nSteps - QWIT handles the differences transparently behind the scenes.\n\n```elixir\ndefmodule MyApp.Work.Flows.Example2 do\n  use QWIT.Flow\n\n  @impl QWIT.Flow\n  def build_flow do\n    step MyApp.Work.Flows.Example, %{arg3: \"value3\"} # arg3 is available to all steps in sub-Flow\n    step MyApp.Work.Steps.Example\n  end\nend\n```\n\n### Oban\n\nOban is the default backend, so you don't have to do anything special to use it.\nHowever, if you prefer to be explicit, you can pass `backend: QWIT.Oban` to your\n`use` statements:\n\n```elixir\n  use QWIT.Flow, backend: QWIT.Oban\n```\n\n```elixir\n  use QWIT.Step, backend: QWIT.Oban\n```\n\n### Custom Engines\n\nDon't see your engine listed here? That's fine - you can write your own! PRs are\nalso happily accepted. Have a look at the `flow.ex` and `step.ex` in\n`lib/qwit/oban` for a good example of how this looks, and how simple it is to\nbuild your own. Don't forget to tell QWIT where to look for your backend!\n\n```elixir\n  use QWIT.Flow, backend: MyBackend\n```\n\n```elixir\n  use QWIT.Step, backend: MyBackend\n```\n\n## Feedback\n\nTo submit feedback, please use the project's\n[GitHub Issues](https://github.com/mu-box/qwit/issues). Unless the feedback is a\nsecurity issue; in that case, email [Dan](mailto:dan.hunsaker+qwit@gmail.com)\ndirectly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmu-box%2Fqwit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmu-box%2Fqwit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmu-box%2Fqwit/lists"}