-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Oban.Worker 'use' macro can't compile with variables #65
Comments
Hi ibarakaiev, could you show me what went wrong when you tried the solution from the readme so I can update it to be more helpful for folks? Thank you, and thanks for taking styler for a spin :) |
@novaugust appreciate your reply! Creating a bare Mix project and adding the following code compiles and works fine: max_attempts = 20
defmodule MyApp.SnoozingWorker do
@moduledoc "#{max_attempts}"
use Oban.Worker, queue: :default, max_attempts: 20
@max_attempts max_attempts
def run do
IO.puts(@max_attempts)
end
end However, using max_attempts = 20
defmodule MyApp.SnoozingWorker do
@moduledoc "#{max_attempts}"
use Oban.Worker, queue: :default, max_attempts: max_attempts
@max_attempts max_attempts
def run do
IO.puts(@max_attempts)
end
end
|
hey @ibarakaiev, had a long weekend, sorry for the delay :) thanks a lot for the repro. something interesting is happening here - i can repro the problem when using exactly your code (oban's use doesn't work), but using a different custom here's the code in oban: this more-or-less identical code compiles defmodule TestUse do
def __using__(opts) do
quote location: :keep do
@after_compile TestUse
def __opts__ do
Keyword.put(unquote(opts), :worker, to_string(__MODULE__))
end
end
end
defmacro __after_compile__(%{module: module}, _env) do
Enum.each(module.__opts__(), &IO.inspect/1)
end
end a_variable = :woo
defmodule MyTestUse do
@moduledoc "#{a_variable}"
use TestUse, a_variable: a_variable
end all of this compiles just fine. so, i'm wondering if something weird happens across dependency boundaries ¯\_(ツ)_/¯ tldr: huh. i'm going to sit on this for now until i understand what's special about oban's |
Any news on this? I just stumbled upon exactly that issue in my code 😕 Styler: 0.10.3 |
alas, i never got anywhere with it. tried tapping some friends to see if they could figure things out but no one knows what the difference is yet. sorry jan :( |
When Interactive Elixir (1.16.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule TestUse do
...(1)> defmacro __using__(opts) do
...(1)> quote location: :keep do
...(1)> def opts do
...(1)> unquote(opts)
...(1)> end
...(1)> end
...(1)> end
...(1)> end
{:module, TestUse,
<<70, 79, 82, 49, 0, 0, 6, 24, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 188,
0, 0, 0, 19, 14, 69, 108, 105, 120, 105, 114, 46, 84, 101, 115, 116, 85, 115,
101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:__using__, 1}}
iex(2)> a_variable = 1
1
iex(3)> defmodule MyTestUse do
...(3)> use TestUse, an_opt: a_variable
...(3)> end
error: undefined variable "a_variable"
└─ iex:4: MyTestUse.opts/0
** (CompileError) iex: cannot compile module MyTestUse (errors have been logged)
(elixir 1.16.0) src/elixir_module.erl:185: anonymous fn/9 in :elixir_module.compile/7 I think it's because the macro doesn't have access to the That's as far as I can sus out before I get a meta-headache. |
woww what a slipup. cheers juan. now i'm just surprised you can get away with doing either! anyways, given that's the issue there's really no good workaround for it right now. |
Yes I agree. In honouring Styler's intention to strictly enforce Credo's So there no simpler way than to refactor as something like this 🤷 max_attempts = 20
defmodule MyApp.SnoozingWorker do
@moduledoc "#{max_attempts}"
use Oban.Worker, queue: :default, max_attempts: 20
@max_attempts max_attempts
def run do
IO.puts(@max_attempts)
end
end |
Ok, there is another way... defmodule TestUse do
defmacro __using__(opts) do
quote location: :keep do
@after_compile TestUse
def opts, do: unquote(opts)
end
end
defmacro __after_compile__(%{module: mod}, _env) do
IO.inspect(mod.opts(), label: "after_compile #{mod}.opts()")
end
end
a_var = :woo
defmodule A do
use TestUse, my_var: unquote(a_var)
end
IO.inspect(A.opts(), label: "runtime A.opts()")
😆 |
eyyy so if folks just do |
First of all, thanks for the amazing work on Styler!
Versions
Example Input
As an example from Oban documentation,
Stacktrace / Current Behaviour
Currently, the output of Styler is:
However, this breaks compilation, as
@max_attempts
is inaccessible whenuse
ingOban.Worker
(it's defined later). The@moduledoc
example in the troubleshooting guide is similar to this, but the provided solution didn't work for me — and, frankly, this seems like it should be handled differently. In the case of@moduledoc
, moving module attributes above it would not be acceptable, but withuse
macros it seems it would be a common use case.The text was updated successfully, but these errors were encountered: