To start, define a Reportable
protocol with a single reportable?/2
function:
defprotocol MyApp.Reportable do
@fallback_to_any true
def reportable?(worker, attempt)
end
defimpl MyApp.Reportable, for: Any do
def reportable?(_worker, _attempt), do: true
end
I set the threshold and added a Reportable implementation inside the worker module:
defmodule MyApp.Workers.FlakyWorker do
use Oban.Worker
defimpl MyApp.Reportable do
@threshold 3
def reportable?(_worker, attempt), do: attempt > @threshold
end
@impl true
def perform(%Oban.Job{args: %{"email" => email}}) do
MyApp.ExternalService.deliver(email)
end
end
At the end I called reportable?/2 from the application’s error reporter, passing the worker module and the attempt number:
defmodule MyApp.ErrorReporter do
alias MyApp.Reportable
def handle_event(_, _, %{attempt: attempt, worker: worker} = meta, _) do
context = Map.take(meta, [:id, :args, :queue, :worker])
if Reportable.reportable?(worker_struct, meta.job.attempt) do
Logger.error("Error", attempt: attempt, error: meta.error, context: context)
end
end
end
final summary
FlakyWorker is not getting the @threshold 3 definition