improvement: various performance improvements

This commit is contained in:
Zach Daniel 2023-10-17 01:08:26 -04:00
parent 52337b7bff
commit 7f7469eb9f
8 changed files with 115 additions and 52 deletions

View file

@ -1314,6 +1314,8 @@ defmodule Ash.Resource.Dsl do
]
@transformers [
Ash.Resource.Transformers.AttributesByName,
Ash.Resource.Transformers.ValidationsAndChangesForType,
Ash.Resource.Transformers.RequireUniqueActionNames,
Ash.Resource.Transformers.SetRelationshipSource,
Ash.Resource.Transformers.BelongsToAttribute,

View file

@ -215,9 +215,15 @@ defmodule Ash.Resource.Info do
Ash.Resource.Validation.t()
]
def validations(resource, type) do
resource
|> validations()
|> Enum.filter(&(type in &1.on))
case Extension.get_persisted(resource, :validations_by_on) do
nil ->
resource
|> validations()
|> Enum.filter(&(type in &1.on))
persisted ->
Map.get(persisted, type) || []
end
end
@doc "A list of all validations for the resource"
@ -233,9 +239,15 @@ defmodule Ash.Resource.Info do
| Ash.Resource.Change.t()
)
def changes(resource, type) do
resource
|> changes()
|> Enum.filter(&(type in &1.on))
case Extension.get_persisted(resource, :changes_by_on) do
nil ->
resource
|> changes()
|> Enum.filter(&(type in &1.on))
persisted ->
Map.get(persisted, type) || []
end
end
@doc "A list of all changes for the resource"
@ -572,15 +584,17 @@ defmodule Ash.Resource.Info do
@spec attribute(Spark.Dsl.t() | Ash.Resource.t(), String.t() | atom) ::
Ash.Resource.Attribute.t() | nil
def attribute(resource, name) when is_binary(name) do
resource
|> attributes()
|> Enum.find(&(to_string(&1.name) == name))
Extension.get_persisted(resource, :attributes_by_name)[name] ||
resource
|> attributes()
|> Enum.find(&(to_string(&1.name) == name))
end
def attribute(resource, name) do
resource
|> attributes()
|> Enum.find(&(&1.name == name))
Extension.get_persisted(resource, :attributes_by_name)[name] ||
resource
|> attributes()
|> Enum.find(&(&1.name == name))
end
@doc "Returns all public attributes of a resource"

View file

@ -0,0 +1,28 @@
defmodule Ash.Resource.Transformers.AttributesByName do
@moduledoc """
Persists attribute_names and attributes_by_name.
"""
use Spark.Dsl.Transformer
alias Spark.Dsl.Transformer
def transform(dsl_state) do
attributes =
Ash.Resource.Info.attributes(dsl_state)
attributes_by_name =
attributes
|> Enum.reduce(%{}, fn %{name: name} = attr, acc ->
acc
|> Map.put(name, attr)
|> Map.put(to_string(name), attr)
end)
attribute_names = Enum.map(attributes, & &1.name)
{:ok,
dsl_state
|> Transformer.persist(:attributes_by_name, attributes_by_name)
|> Transformer.persist(:attribute_names, attribute_names)}
end
end

View file

@ -0,0 +1,37 @@
defmodule Ash.Resource.Transformers.ValidationsAndChangesForType do
@moduledoc """
Persists global changes/validations and what type they go on.
"""
use Spark.Dsl.Transformer
alias Spark.Dsl.Transformer
def transform(dsl_state) do
validations_by_on =
dsl_state
|> Ash.Resource.Info.validations()
|> Enum.reduce(%{}, fn validation, acc ->
validation.on
|> List.wrap()
|> Enum.reduce(acc, fn on, acc ->
Map.update(acc, on, [validation], &[validation | &1])
end)
end)
changes_by_on =
dsl_state
|> Ash.Resource.Info.changes()
|> Enum.reduce(%{}, fn change, acc ->
change.on
|> List.wrap()
|> Enum.reduce(acc, fn on, acc ->
Map.update(acc, on, [change], &[change | &1])
end)
end)
{:ok,
dsl_state
|> Transformer.persist(:validations_by_on, validations_by_on)
|> Transformer.persist(:changes_by_on, changes_by_on)}
end
end

View file

@ -110,16 +110,10 @@ defmodule Ash.Type.NewType do
@impl Ash.Type
def cast_input(value, constraints) do
case unquote(subtype_of).cast_input(
value,
constraints
) do
{:ok, value} ->
apply_constraints(value, constraints)
other ->
other
end
unquote(subtype_of).cast_input(
value,
constraints
)
end
if function_exported?(subtype_of, :cast_input_array, 2) do

View file

@ -258,11 +258,7 @@ defmodule Ash.Type do
end
def array_constraints(type) do
if ash_type?(type) do
type.array_constraints()
else
[]
end
type.array_constraints()
end
@spec get_type(atom | module | {:array, atom | module}) ::
@ -271,11 +267,12 @@ defmodule Ash.Type do
{:array, get_type(value)}
end
for {short_name, value} <- @short_names do
def get_type(unquote(short_name)), do: unquote(value)
end
def get_type(value) when is_atom(value) do
case Keyword.fetch(@short_names, value) do
{:ok, mod} -> mod
:error -> value
end
value
end
def get_type(value) do
@ -663,13 +660,9 @@ defmodule Ash.Type do
def apply_constraints(type, term, constraints) do
type = get_type(type)
if ash_type?(type) do
case type.apply_constraints(term, constraints) do
:ok -> {:ok, term}
other -> other
end
else
{:ok, term}
case type.apply_constraints(term, constraints) do
:ok -> {:ok, term}
other -> other
end
end
@ -720,11 +713,8 @@ defmodule Ash.Type do
end
def constraints(type) do
if ash_type?(type) do
type.constraints()
else
[]
end
type = get_type(type)
type.constraints()
end
def cast_in_query?(type, constraints \\ [])
@ -734,14 +724,12 @@ defmodule Ash.Type do
end
def cast_in_query?(type, constraints) do
if ash_type?(type) do
if function_exported?(type, :cast_in_query?, 0) do
type.cast_in_query?()
else
type.cast_in_query?(constraints)
end
type = get_type(type)
if function_exported?(type, :cast_in_query?, 0) do
type.cast_in_query?()
else
false
type.cast_in_query?(constraints)
end
end

View file

@ -302,7 +302,7 @@ defmodule Ash.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:spark, "~> 1.1 and >= 1.1.20"},
{:spark, "~> 1.1 and >= 1.1.47"},
{:ecto, "~> 3.7"},
{:ets, "~> 0.8"},
{:decimal, "~> 2.0"},

View file

@ -31,7 +31,7 @@
"plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
"sourceror": {:hex, :sourceror, "0.14.0", "b6b8552d0240400d66b6f107c1bab7ac1726e998efc797f178b7b517e928e314", [:mix], [], "hexpm", "809c71270ad48092d40bbe251a133e49ae229433ce103f762a2373b7a10a8d8b"},
"spark": {:hex, :spark, "1.1.44", "be9f2669b03ae43447bda77045598a4500988538a7d0ba576b8e306332822147", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "e49bf5ca770cb0bb9cac7ed8da5eb7871156b3236c8c535f3f4caa93377059a3"},
"spark": {:hex, :spark, "1.1.47", "2bc334e542f519709e57853a425aa9304223c61e3ecf130b1cc014c6a4451f9a", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "c1ae778a3779b5d3e5b7c885cc9826577816dca10bbf4c21638198a1262f3df1"},
"statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},
"stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},