# `GoodJob`
[🔗](https://github.com/amkisko/good_job.ex/blob/v1.0.0/lib/good_job.ex#L1)

GoodJob is a concurrent, Postgres-based job queue backend for Elixir.

GoodJob provides a complete job queue system with:
- PostgreSQL backend with advisory locks
- LISTEN/NOTIFY for low-latency job dispatch
- Cron-like scheduled jobs
- Batch job support
- Concurrency controls
- Retry mechanisms

## Configuration

    config :good_job,
      repo: MyApp.Repo,
      queues: "*",
      max_processes: 5,
      poll_interval: 10

## Usage

    # Define a job
    defmodule MyApp.MyJob do
      use GoodJob.Job

      def perform(%{data: data}) do
        # Your job logic
      end
    end

    # Enqueue a job
    MyApp.MyJob.enqueue(%{data: "hello"})

# `cleanup_preserved_jobs`

Cleans up preserved job records older than the specified time.

## Options

  * `:older_than` - Jobs older than this (in seconds) will be deleted. Default: 14 days
  * `:include_discarded` - Whether to include discarded jobs. Default: config `cleanup_discarded_jobs` (`true`)
  * `:max_count` - Maximum number of preserved jobs/executions to keep. Default: config `cleanup_preserved_jobs_max_count` (`nil`)

# `config`

Returns the current configuration.

# `enqueue`

Enqueues a job for execution.

## Examples

    GoodJob.enqueue(MyApp.MyJob, %{data: "hello"})

    GoodJob.enqueue(MyApp.MyJob, %{data: "hello"}, queue: "high_priority", priority: 1)

    # With concurrency control (limits from module or opts; see :concurrency_config)
    GoodJob.enqueue(MyApp.MyJob, %{data: "hello"}, concurrency_key: "user_123", concurrency_config: [total_limit: 5])

    # Execute inline (synchronously)
    GoodJob.enqueue(MyApp.MyJob, %{data: "hello"}, execution_mode: :inline)

    # Bulk enqueue (single NOTIFY): used by `GoodJob.Batch.enqueue_all/1`
    GoodJob.enqueue(MyApp.MyJob, %{data: "hello"}, batch_id: batch_id, listen_notify: false)

# `new_batch`

Creates a new batch for grouping jobs together.

# `pause`

Pauses job execution for a given queue or job class.

## Options

  * `:queue` - Queue name to pause
  * `:job_class` - Job class name to pause

# `paused?`

Checks if job execution is paused for a given queue or job class.

## Options

  * `:queue` - Queue name to check
  * `:job_class` - Job class name to check

# `shutdown`

Shuts down all GoodJob processes gracefully.

## Options

  * `:timeout` - Timeout in milliseconds to wait for shutdown. Default: `-1` (wait forever)

# `shutdown?`

Checks if GoodJob is shut down.

# `stats`

```elixir
@spec stats() :: map()
```

Returns job statistics for all queues.

# `stats`

```elixir
@spec stats(String.t()) :: map()
```

Returns job statistics for a specific queue.

# `unpause`

Unpauses job execution for a given queue or job class.

## Options

  * `:queue` - Queue name to unpause
  * `:job_class` - Job class name to unpause

---

*Consult [api-reference.md](api-reference.md) for complete listing*
