Skip to content

Commit

Permalink
Parse adapter out of repo module using zippers
Browse files Browse the repository at this point in the history
  • Loading branch information
sorentwo committed Dec 28, 2024
1 parent d3b8875 commit 226d150
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 25 deletions.
3 changes: 1 addition & 2 deletions .credo.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
# You can customize the priority of any check
# Priority values are: `low, normal, high, higher`
#
{Credo.Check.Design.AliasUsage,
[priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 2]},
{Credo.Check.Design.AliasUsage, false},
{Credo.Check.Design.TagTODO, [exit_status: 2]},
{Credo.Check.Design.TagFIXME, []},

Expand Down
46 changes: 31 additions & 15 deletions lib/mix/tasks/oban.install.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ if Code.ensure_loaded?(Igniter) do
opts = igniter.args.options

case extract_repo(igniter, app_name, opts[:repo]) do
{:ok, repo} ->
engine = parse_engine(repo, opts[:engine])
notifier = parse_notifier(repo, opts[:notifier])
{:ok, repo, adapter} ->
engine = parse_engine(adapter, opts[:engine])
notifier = parse_notifier(adapter, opts[:notifier])

conf_code = [engine: engine, notifier: notifier, queues: [default: 10], repo: repo]
test_code = [testing: :manual]
Expand Down Expand Up @@ -101,9 +101,9 @@ if Code.ensure_loaded?(Igniter) do
end

defp extract_repo(igniter, app_name, nil) do
case Application.get_env(app_name, :ecto_repos, []) do
[repo | _] ->
{:ok, repo}
case Igniter.Libs.Ecto.list_repos(igniter) do
{igniter, [repo | _]} ->
{:ok, repo, extract_adapter(igniter, repo)}

_ ->
issue = """
Expand All @@ -119,31 +119,47 @@ if Code.ensure_loaded?(Igniter) do
defp extract_repo(igniter, _app_name, module) do
repo = Igniter.Project.Module.parse(module)

if Code.ensure_loaded?(repo) do
{:ok, repo}
case Igniter.Project.Module.module_exists(igniter, repo) do
{true, igniter} ->
{:ok, repo, extract_adapter(igniter, repo)}

{false, _} ->
{:error, Igniter.add_issue(igniter, "Provided repo (#{inspect(repo)}) doesn't exist")}
end
end

defp extract_adapter(igniter, repo) do
match_use = &match?({:use, _, [{:__aliases__, _, [:Ecto, :Repo]} | _]}, &1.node)
match_adp = &match?({{:__block__, _, [:adapter]}, {:__aliases__, _, _}}, &1.node)

with {:ok, {_, _, zipper}} <- Igniter.Project.Module.find_module(igniter, repo),
{:ok, zipper} <- Igniter.Code.Common.move_to(zipper, match_use),
{:ok, zipper} <- Igniter.Code.Common.move_to(zipper, match_adp),
{:ok, {:adapter, adapter}} <- Igniter.Code.Common.expand_literal(zipper) do
adapter
else
{:error, Igniter.add_issue(igniter, "The provided repo (#{inspect(repo)}) doesn't exist")}
_ -> Ecto.Adapters.Postgres
end
end

defp parse_engine(repo, nil) do
case repo.__adapter__() do
defp parse_engine(adapter, nil) do
case adapter do
Ecto.Adapters.Postgres -> Oban.Engines.Basic
Ecto.Adapters.MyXQL -> Oban.Engines.Dolphin
Ecto.Adapters.SQLite3 -> Oban.Engines.Lite
end
end

defp parse_engine(_repo, module), do: Igniter.Project.Module.parse(module)
defp parse_engine(_, module), do: Igniter.Project.Module.parse(module)

defp parse_notifier(repo, nil) do
case repo.__adapter__() do
defp parse_notifier(adapter, nil) do
case adapter do
Ecto.Adapters.Postgres -> Oban.Notifiers.Postgres
_ -> Oban.Notifiers.PG
end
end

defp parse_notifier(_repo, module), do: Igniter.Project.Module.parse(module)
defp parse_notifier(_, module), do: Igniter.Project.Module.parse(module)
end
else
defmodule Mix.Tasks.Oban.Install do
Expand Down
33 changes: 25 additions & 8 deletions test/mix/tasks/oban.install_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ defmodule Mix.Tasks.Oban.InstallTest do

import Igniter.Test

alias Mix.Tasks.Oban.Install

describe "install" do
test "installing without an available ecto repo" do
assert {:error, [warning]} =
test_project()
|> Install.igniter()
|> Igniter.compose_task("oban.install", [])
|> apply_igniter()

assert warning =~ "No ecto repos found for :test"
Expand All @@ -30,9 +28,21 @@ defmodule Mix.Tasks.Oban.InstallTest do
end
"""

[app_name: :oban, files: %{"lib/oban/application.ex" => application}]
repo = """
defmodule Oban.Test.Repo do
@moduledoc false
use MyApp.CustomMacro, otp_app: :oban
use Ecto.Repo, otp_app: :oban, adapter: Ecto.Adapters.Postgres
end
"""

files = %{"lib/oban/application.ex" => application, "lib/oban/repo.ex" => repo}

[app_name: :oban, files: files]
|> test_project()
|> Install.igniter()
|> Igniter.compose_task("oban.install", [])
|> assert_has_patch("config/config.exs", """
| config :oban, Oban,
| engine: Oban.Engines.Basic,
Expand All @@ -50,10 +60,17 @@ defmodule Mix.Tasks.Oban.InstallTest do
end

test "installing selects correct config with alternate repo" do
[app_name: :oban]
repo = """
defmodule Oban.Test.LiteRepo do
@moduledoc false
use Ecto.Repo, otp_app: :oban, adapter: Ecto.Adapters.SQLite3
end
"""

[app_name: :oban, files: %{"lib/oban/repo.ex" => repo}]
|> test_project()
|> Map.replace!(:args, %{options: [repo: "Oban.Test.LiteRepo"]})
|> Install.igniter()
|> Igniter.compose_task("oban.install", ["--repo", "Oban.Test.LiteRepo"])
|> assert_has_patch("config/config.exs", """
| config :oban, Oban,
| engine: Oban.Engines.Lite,
Expand Down

0 comments on commit 226d150

Please sign in to comment.