README.md

<picture>
  <img src="./logo.png" alt="Oban Doctor logo" />
</picture>

# ObanDoctor

[![Hex.pm](https://img.shields.io/hexpm/v/oban_doctor.svg)](https://hex.pm/packages/oban_doctor)
[![Documentation](https://img.shields.io/badge/docs-hexdocs-blue.svg)](https://hexdocs.pm/oban_doctor/readme.html)
[![Coverage Status](https://coveralls.io/repos/github/tomasz-tomczyk/oban_doctor/badge.svg?branch=main)](https://coveralls.io/github/tomasz-tomczyk/oban_doctor?branch=main)

Static analysis tool for Oban workers and configuration. Catches misconfigurations and worker bugs at CI time through AST parsing. Based on lessons learnt over many years of happily using Oban.

## Installation

Add `oban_doctor` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:oban_doctor, "~> 0.1", only: [:dev, :test], runtime: false}
  ]
end
```

## Usage

Run all checks:

```bash
mix oban_doctor
```

Or run specific check types:

```bash
mix oban_doctor.check_workers  # Worker checks only
mix oban_doctor.check_config   # Config checks only
```

Options:

- `--format=json` - Output as JSON (for CI integration)
- `--strict` - Treat warnings as errors (exit code 1)
- `--verbose` - Show detailed output

## Checks

### Worker Checks

| Check                                                                                                          | Description                                                         |
| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| [MissingQueue](https://hexdocs.pm/oban_doctor/ObanDoctor.Check.Worker.MissingQueue.html)                       | Detects workers using queues not defined in Oban configuration      |
| [StateGroupUsage](https://hexdocs.pm/oban_doctor/ObanDoctor.Check.Worker.StateGroupUsage.html)                 | Detects workers using the dangerous `:all` state group              |
| [UniquenessMissingStates](https://hexdocs.pm/oban_doctor/ObanDoctor.Check.Worker.UniquenessMissingStates.html) | Detects unique configs missing recommended states like `:retryable` |
| [UniqueWithoutKeys](https://hexdocs.pm/oban_doctor/ObanDoctor.Check.Worker.UniqueWithoutKeys.html)             | Detects unique constraints on `:args` without explicit `keys`       |
| [NoMaxAttempts](https://hexdocs.pm/oban_doctor/ObanDoctor.Check.Worker.NoMaxAttempts.html)                     | Detects workers using the default `max_attempts` of 20              |

### Config Checks

| Check                                                                                                    | Description                                                                   |
| -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| [InsertTriggerEnabled](https://hexdocs.pm/oban_doctor/ObanDoctor.Check.Config.InsertTriggerEnabled.html) | Detects Oban instances without `insert_trigger: false` (performance overhead) |
| [MissingPruner](https://hexdocs.pm/oban_doctor/ObanDoctor.Check.Config.MissingPruner.html)               | Detects Oban instances without a pruner plugin (jobs accumulate indefinitely) |
| [NoReindexer](https://hexdocs.pm/oban_doctor/ObanDoctor.Check.Config.NoReindexer.html)                   | Detects Oban instances without the Reindexer plugin (index bloat)             |

## Configuration

Create a `.oban_doctor.exs` file in your project root to customize behavior:

```bash
mix oban_doctor.gen.config
```

Example:

```elixir
[
  checks: [
    # Disable a check entirely
    unique_without_keys: [enabled: false],

    # Override severity
    no_max_attempts: [severity: :info],

    # Exclude specific workers from a worker check
    missing_queue: [
      excluded_workers: [MyApp.Workers.LegacyWorker]
    ],

    # Exclude specific Oban instances from a config check
    missing_pruner: [
      excluded_instances: [MyApp.SecondaryOban]
    ]
  ],

  # Exclude workers from ALL worker checks
  excluded_workers: [MyApp.Workers.DeprecatedWorker],

  # Exclude files from ALL checks
  excluded_files: ["test/support/"]
]
```

See the [Configuration Guide](https://hexdocs.pm/oban_doctor/configuration.html) for full documentation.

## CI Integration

Add to your CI pipeline:

```bash
mix oban_doctor --strict
```

For JSON output (useful for custom reporting):

```bash
mix oban_doctor --format=json
```

Exit codes:

- `0` - No errors (warnings are allowed unless `--strict`)
- `1` - Errors found (or warnings with `--strict`)

## License

Apache 2.0