Oban Pro: overriding Oban.Pro.Worker.new/2

I’m exploring structured workers in Oban Pro – this is a nice feature!

I’m trying to reduce redundant code and have reasonably clear interfaces for my functions. One concern is that the struct for the structured worker looks nearly identical to one of our Ecto structs. I think it’s probably good to have a degree of abstraction separating the 2 structs, but I’m wondering if there’s any way to reuse some of the definitions?

Secondly, I find it a bit more clear if we pass one of our Ecto structs to enqueue as a (structured) Oban job. We don’t want to implement the Jason encoding protocol, so I’ve found it useful to override the new/2 function in the worker module (i.e. the one that uses Oban.Pro.Worker) so I can handle the input in a way that makes sense for our app. However, the new/2 function doesn’t seem to like the default opts that come through…

I would expect this to work:

def new(args, opts) do
    # ... custom tweaks to args here ...
    Job.new(args, opts)
  end

but this generates some errors:

     Expected args and opts to build a valid job, got validation errors:

     base: unknown option :stages provided

So I have found myself doing something like this:

def new(args, opts) do
    opts = __opts__() |> Worker.merge_opts(opts) |> Keyword.delete(:stages)
    # ... custom tweaks to args here ...
    Job.new(args, opts)
  end

That seems to work, but it looks a bit hacky. Can someone point out a cleaner way to do this? Did I improperly implement the new/2 function? Is there a better way to override this?

You overrode it properly, but you should use super(args, opts) instead. That will call the original version of new/2 and correctly handle the non-standard options.

Got it – thanks! I had forgotten about this trick

1 Like