improvement: don't install sat solver in initial installation

improvement: ask user to install sat solver when extending with policies
improvement: validate that a solver exists at compile time when using policies
This commit is contained in:
Zach Daniel 2024-07-24 16:08:39 -04:00
parent 62bda80b38
commit 381870ac3e
4 changed files with 68 additions and 13 deletions

View file

@ -410,7 +410,8 @@ defmodule Ash.Policy.Authorizer do
]
@verifiers [
Ash.Policy.Authorizer.Verifiers.VerifyInAuthorizers
Ash.Policy.Authorizer.Verifiers.VerifyInAuthorizers,
Ash.Policy.Authorizer.Verifiers.VerifySatSolverImplementation
]
use Spark.Dsl.Extension,
@ -453,6 +454,38 @@ defmodule Ash.Policy.Authorizer do
)
end
def install(igniter, module, type, _path, _argv) do
igniter =
with nil <- Igniter.Project.Deps.get_dependency_declaration(igniter, :picosat_elixir),
nil <- Igniter.Project.Deps.get_dependency_declaration(igniter, :simple_sat) do
solver =
Owl.IO.select(
[
{:picosat_elixir, "~> 0.2"},
{:simple_sat, "~> 0.1"}
],
label:
"Which sat solver would you like to use? If on windows, use `simple_sat`, otherwise, use `picosat_elixir`.",
render_as: &to_string(elem(&1, 0))
)
igniter
|> Igniter.Project.Deps.add_dep(solver)
|> Igniter.apply_and_fetch_dependencies()
else
_ ->
igniter
end
igniter
|> Spark.Igniter.add_extension(
module,
type,
:authorizers,
Ash.Policy.Authorizer
)
end
@doc false
# We can't actually validate that they are check modules here
# without causing compile time dependencies

View file

@ -0,0 +1,9 @@
defmodule Ash.Policy.Authorizer.Verifiers.VerifySatSolverImplementation do
@moduledoc false
use Spark.Dsl.Verifier
def verify(_dsl) do
Ash.SatSolver.Implementation.check!()
:ok
end
end

View file

@ -36,8 +36,7 @@ defmodule Mix.Tasks.Ash.Install do
@impl Igniter.Mix.Task
def info(_argv, _source) do
%Igniter.Mix.Task.Info{
composes: ["spark.install"],
adds_deps: [picosat_elixir: "~> 0.2"]
composes: ["spark.install"]
}
end

View file

@ -5,6 +5,8 @@ cond do
def solve_expression(cnf) do
Module.concat([System.get_env("SAT_SOLVER") || "Picosat"]).solve(cnf)
end
def check!, do: :ok
end
Code.ensure_loaded?(Picosat) ->
@ -13,6 +15,8 @@ cond do
def solve_expression(cnf) do
Picosat.solve(cnf)
end
def check!, do: :ok
end
Code.ensure_loaded?(SimpleSat) ->
@ -21,31 +25,41 @@ cond do
def solve_expression(cnf) do
SimpleSat.solve(cnf)
end
def check!, do: :ok
end
true ->
defmodule Ash.SatSolver.Implementation do
@moduledoc false
def solve_expression(_cnf) do
check!()
:ok
end
def check! do
if Code.ensure_loaded?(Picosat) || Code.ensure_loaded?(SimpleSat) do
raise """
No SAT solver available, although one was loaded. This typically means you need to run `mix deps.compile ash --force`
No SAT solver available, although one was loaded.
This typically means that you need to run `mix deps.compile ash --force`
If that doesn't work, please ensure that one of the following dependencies is present in your application to use sat solver features:
* `:picosat_elixir` (recommended) - A NIF wrapper around the PicoSAT SAT solver. Fast, production ready, battle tested.
* `:simple_sat` - A pure Elixir SAT solver. Slower than PicoSAT, but no NIF dependency.
"""
else
raise """
No SAT solver available.
Please add one of the following dependencies to your application to use sat solver features:
* `:picosat_elixir` (recommended) - A NIF wrapper around the PicoSAT SAT solver. Fast, production ready, battle tested.
* `:simple_sat` - A pure Elixir SAT solver. Slower than PicoSAT, but no NIF dependency.
"""
end
raise """
No SAT solver available.
Please add one of the following dependencies to your application to use sat solver features:
* `:picosat_elixir` (recommended) - A NIF wrapper around the PicoSAT SAT solver. Fast, production ready, battle tested.
* `:simple_sat` - A pure Elixir SAT solver. Slower than PicoSAT, but no NIF dependency.
"""
end
end
end