Current section
Files
Jump to
Current section
Files
lib/faktory/middleware.ex
defmodule Faktory.Middleware do
@moduledoc ~S"""
Middleware behaviour for client (enqueing) and worker (dequeing/processing).
On the client side, a middleware chain alters a job before it is enqueued.
On the worker side, a middleware chain alters a job before it is processed.
It's just a simple behaviour that requires `call/3`. Almost no reason to
even make it a behaviour other than having a module to attach documentation to.
Let's make worker middleware that logs how long jobs take to process.
```elixir
defmodule JobTimer do
use Faktory.Middleware
import Faktory.Utils, only: [now_in_ms: 0]
require Logger
def call(job, chain, f) do
# Alter the job by putting a start time in the custom field.
job = job
|> Map.put_new("custom", %{})
|> put_in(["custom", "start_time"], now_in_ms())
# Pass it along to get processed.
job = f.(job, chain)
# Calculate the elapse time.
elapsed = now_in_ms() - job["custom"]["start_time"]
elapsed = (elapsed / 1000) |> Float.round(3)
jid = job["jid"]
Logger.info("Job #{jid} took #{elapsed} seconds!")
# Always return the job for other middlewares further up the chain.
job
end
end
```
Next add it to the worker configuration.
```elixir
defmodule WorkerConf do
use Faktory.Configuration, :worker
middleware [JobTimer]
end
```
Super contrived because we don't actually need to alter the job to time it.
It's just meant to illustrate the idea of altering a job in a way that other
middlewares further up or down the chain can see the change.
It is important to capture the changes to the job after passing it along:
```elixir
job = f.(job, chain)
```
That way you can see any changes made after handing it off and it comes
back down the chain after being processed.
"""
defmacro __using__(_options) do
quote do
@behaviour Faktory.Middleware
end
end
@type job :: map
@type chain :: [module]
@doc """
Invokes the middleware
It's hard to explain. Just look at the example in the moduledoc.
"""
@callback call(job, chain, (job, chain -> job)) :: job
end