I have a hook that implements before_process/1 and use it to log and pub_sub.
I noticed that, if I have a job currently in executing state, if I call Oban.cancel_job for it, before_process/1 will be called again before after_process(:cancel, …) is called.
Why is that?
This creates some issues to my case since I’m using this hook to send pub_sub messages, meaning that I end up sending a “wrong” executing message event (I send it if before_process/1 is called).
Btw, this seems to only happen using before_process/1, using telemetry [:oban, :job, :start] work fine.
This is by design and intentional. The cancel event is handled by a different process from the job. When the hook fires in a new process, there isn’t any stored/prepared job data, so before_process/1 is called again to reconstruct the job state before calling after_process/3 hooks.
This is done to ensure hooks have consistent job state, including any potential pre-processing that was done in before_process/1. The :start telemetry isn’t fired before cancellation, which is why it works the way you expect.
Got it, in that case, is there something that I can see in the before_process job struct that would allow me to identify if it was called to be cancel or not so I can differentiate these calls from the rest?
Generally, the before_process hook should be used for idempotent pre-processing rather than side-effects. But, you can detect whether it’s being called to cancel by checking if the process has a label:
if :proc_lib.get_label(self()) == :undefined do
# This is for a cancellation call and it isn't running in the job process
else
# This is running in the job process and the label will be the worker name
end