# Background Tasks and Jobs

## Once off background tasks

When you just want to run some code in a background task then you can use `PetalPro.BackgroundTask.run/1`:

```elixir
PetalPro.BackgroundTask.run(fn ->
  do_some_time_instensive_stuff()
end)
```

This can be useful for speeding up responses in a HTTP request or LiveView action - you delegate anything that takes time to a background task (eg sending emails, sending to Slack, creating a log, etc.). Since we want to respond to a user request as soon as possible, you run these other non-essential tasks in a background task and it won't hold up the response.

## Background jobs with Oban

A background job is a something you want to run outside of a normal HTTP request/response cycle. Things like sending weekly emails or processing images. We use [Oban](https://github.com/sorentwo/oban) for this.

A background job is performed by a "worker". Each worker gets its own file. Petal Pro comes with an example worker you can duplicate:

```elixir
defmodule PetalPro.Workers.ExampleWorker do
  @moduledoc """
  Example of how to do async work with Oban.

  Run with:
  Oban.insert(PetalPro.Workers.ExampleWorker.new(%{}))
  """
  use Oban.Worker, queue: :default
  require Logger

  @impl Oban.Worker
  def perform(%Oban.Job{} = _job) do
    today = Timex.now() |> Timex.to_date()
    Logger.info("ExampleWorker: Today is #{today}")
    :ok
  end
end
```

You can run this worker by inserting a job into the database:

```elixir
Oban.insert(PetalPro.Workers.ExampleWorker.new(%{}))
```

Once in the database, Oban will try running the task and retry it if it fails. You can see any failed jobs by checking the database:

![Oban jobs show up in the "oban\_jobs" table](https://50448613-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSwy36CS0dsnIH4ah9iHk%2Fuploads%2FOaQGLfEXaA71x0A39wmx%2Foban_in_db.png?alt=media\&token=18ac3f7a-5c0c-4ed4-967d-29a2bb86b18c)

&#x20;Jobs that have been completed are deleted every 24 hours so your database won't swell over time.

### Cron jobs

You can tell your workers to work at certain times with Oban's CRON functionality. See the examples in `config.exs:`

```
config :petal_pro, Oban,
  repo: PetalPro.Repo,
  queues: [default: 5],
  plugins: [
    {Oban.Plugins.Pruner, max_age: (3600 * 24)},
    {Oban.Plugins.Cron,
      crontab: [
        {"@daily", PetalPro.Workers.ExampleWorker}
        # {"* * * * *", PetalPro.EveryMinuteWorker},
        # {"0 * * * *", PetalPro.EveryHourWorker},
        # {"0 */6 * * *", PetalPro.EverySixHoursWorker},
        # {"0 0 * * SUN", PetalPro.EverySundayWorker},
        # More examples: https://crontab.guru/examples.html
      ]}
  ]
```
