Hi there, I would like to know your thoughts about how to use Oban workers in a Phoenix app with Scopes.
When using scopes the context functions receive as first parameter the scope, f.e.
# lib/my_app/blog.ex
def list_posts(%Scope{} = scope) do
Repo.all(from post in Post, where: post.user_id == ^scope.user.id)
end
If I needed to use the list_posts inside a worker, I’ll need somehow to build a scope in order to use those scoped functions:
defmodule MyApp.MyWorker do
use Oban.Worker
@impl Oban.Worker
def perform(%Oban.Job{args: %{"id" => id}}) do
scope = # ? how to get the scope at the time the worker runs
list = Blog.list_posts(scope)
# Do something with list
:ok
end
end
Option 1.
Pass the scope (or enought data to rebuild the scope) as params to `Worker.new()`
%{user_id: scope.user.id, other: "data"}
|> MyApp.Worker.new()
|> Oban.insert()
and in the worker use user_id to build a `scope` and continue from that.
Option 2.
Add additional heads in the Context that don’t require scope and are only used by trusted callers (in this case Oban)
# lib/my_app/blog.ex
# additional function head that does not use scope
def list_posts(user_id) do
Repo.all(from post in Post, where: post.user_id == ^user_id)
end
defmodule MyApp.MyWorker do
use Oban.Worker
@impl Oban.Worker
def perform(%Oban.Job{args: %{"id" => user_id}}) do
# use the non-scoped functions
list = Blog.list_posts(user_id)
# Do something with list
:ok
end
end
None of the options is optimal, but from those two, the option 2 is the worst as it totally breaks the idea of scopes in the context modules by allowing anyone to bypass the scoped functions and use the non-scoped ones.
So I’m leaning on passing enough info to the worker params and use that to build a scope inside it and then use it to do whatever thing the worker needs to do using the scoped context functions.
Is there another way?
Do you have suggestions/ideas/experience implementing something like this?
Thanks in advance,
Miguel Cobá






















