Skip to content

Commit 10cf60c

Browse files
committed
fix: remove Agent "convenience" for determining min pg version
We need to require that users provide this function. To that end we're adding a warning in a minor release branch telling users to define this. The agent was acting as a bottleneck that all queries must go through, causing nontrivial performance issues at scale.
1 parent a539f64 commit 10cf60c

File tree

6 files changed

+40
-110
lines changed

6 files changed

+40
-110
lines changed

lib/data_layer/info.ex

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,15 @@ defmodule AshPostgres.DataLayer.Info do
4242
@doc "Gets the resource's repo's postgres version"
4343
def min_pg_version(resource) do
4444
case repo(resource, :read).min_pg_version() do
45-
%Version{} = version -> version
46-
string when is_binary(string) -> Version.parse!(string)
45+
%Version{} = version ->
46+
version
47+
48+
string when is_binary(string) ->
49+
IO.warn(
50+
"Got a `string` for min_pg_version, expected a `Version` struct. Got: #{inspect(string)}. Please call `Version.parse!` before returning the value."
51+
)
52+
53+
Version.parse!(string)
4754
end
4855
end
4956

lib/repo.ex

Lines changed: 1 addition & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ defmodule AshPostgres.Repo do
8686
otp_app: otp_app
8787
end
8888

89-
@agent __MODULE__.AshPgVersion
9089
@behaviour AshPostgres.Repo
9190
@warn_on_missing_ash_functions Keyword.get(opts, :warn_on_missing_ash_functions?, true)
9291
@after_compile __MODULE__
92+
@before_compile AshPostgres.Repo.BeforeCompile
9393
require Logger
9494

9595
defoverridable insert: 2, insert: 1, insert!: 2, insert!: 1
@@ -123,18 +123,6 @@ defmodule AshPostgres.Repo do
123123
end
124124

125125
def init(type, config) do
126-
if type == :supervisor do
127-
try do
128-
Agent.stop(@agent)
129-
rescue
130-
_ ->
131-
:ok
132-
catch
133-
_, _ ->
134-
:ok
135-
end
136-
end
137-
138126
new_config =
139127
config
140128
|> Keyword.put(:installed_extensions, installed_extensions())
@@ -208,97 +196,6 @@ defmodule AshPostgres.Repo do
208196
end
209197
end
210198

211-
def min_pg_version do
212-
if version = cached_version() do
213-
version
214-
else
215-
lookup_version()
216-
end
217-
end
218-
219-
defp cached_version do
220-
if config()[:pool] == Ecto.Adapters.SQL.Sandbox do
221-
Agent.start_link(
222-
fn ->
223-
nil
224-
end,
225-
name: @agent
226-
)
227-
228-
case Agent.get(@agent, fn state -> state end) do
229-
nil ->
230-
version = lookup_version()
231-
232-
Agent.update(@agent, fn _ ->
233-
version
234-
end)
235-
236-
version
237-
238-
version ->
239-
version
240-
end
241-
else
242-
Agent.start_link(
243-
fn ->
244-
lookup_version()
245-
end,
246-
name: @agent
247-
)
248-
249-
Agent.get(@agent, fn state -> state end)
250-
end
251-
end
252-
253-
defp lookup_version do
254-
version_string =
255-
try do
256-
query!("SELECT version()").rows |> Enum.at(0) |> Enum.at(0)
257-
rescue
258-
error ->
259-
reraise """
260-
Got an error while trying to read postgres version
261-
262-
Error:
263-
264-
#{inspect(error)}
265-
""",
266-
__STACKTRACE__
267-
end
268-
269-
try do
270-
version_string
271-
|> String.split(" ")
272-
|> Enum.at(1)
273-
|> String.split(".")
274-
|> case do
275-
[major] ->
276-
"#{major}.0.0"
277-
278-
[major, minor] ->
279-
"#{major}.#{minor}.0"
280-
281-
other ->
282-
Enum.join(other, ".")
283-
end
284-
|> Version.parse!()
285-
rescue
286-
error ->
287-
reraise(
288-
"""
289-
Could not parse postgres version from version string: "#{version_string}"
290-
291-
You may need to define the `min_version/0` callback yourself.
292-
293-
Error:
294-
295-
#{inspect(error)}
296-
""",
297-
__STACKTRACE__
298-
)
299-
end
300-
end
301-
302199
def from_ecto(other), do: other
303200

304201
def to_ecto(nil), do: nil
@@ -336,7 +233,6 @@ defmodule AshPostgres.Repo do
336233
defoverridable init: 2,
337234
on_transaction_begin: 1,
338235
installed_extensions: 0,
339-
min_pg_version: 0,
340236
all_tenants: 0,
341237
tenant_migrations_path: 0,
342238
default_prefix: 0,

lib/repo/before_compile.ex

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
defmodule AshPostgres.Repo.BeforeCompile do
2+
@moduledoc false
3+
4+
defmacro __before_compile__(_env) do
5+
quote do
6+
unless Module.defines?(__MODULE__, {:min_pg_version, 0}, :def) do
7+
IO.warn("""
8+
Please define `min_pg_version/0` in repo module: #{inspect(__MODULE__)}
9+
10+
For example:
11+
12+
def min_pg_version do
13+
%Version{major: 16, minor: 0, patch: 0}
14+
end
15+
16+
The lowest compatible version is being assumed.
17+
""")
18+
19+
def min_pg_version do
20+
%Version{major: 13, minor: 0, patch: 0}
21+
end
22+
end
23+
end
24+
end
25+
end

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"simple_sat": {:hex, :simple_sat, "0.1.3", "f650fc3c184a5fe741868b5ac56dc77fdbb428468f6dbf1978e14d0334497578", [:mix], [], "hexpm", "a54305066a356b7194dc81db2a89232bacdc0b3edaef68ed9aba28dcbc34887b"},
4040
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
4141
"sourceror": {:hex, :sourceror, "1.6.0", "9907884e1449a4bd7dbaabe95088ed4d9a09c3c791fb0103964e6316bc9448a7", [:mix], [], "hexpm", "e90aef8c82dacf32c89c8ef83d1416fc343cd3e5556773eeffd2c1e3f991f699"},
42-
"spark": {:hex, :spark, "2.2.11", "6589ac0e50d69e5095871a5e8f3bb6107755b1cc71f05a31d7398902506dab9a", [:mix], [{:igniter, ">= 0.2.6 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.2", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "662d297d0ad49a5990a72cbf342d70e90894218062da2893f2df529f70ecc2b4"},
42+
"spark": {:hex, :spark, "2.2.16", "221f18b302f8b2df28ac5664c4a1abc8b9c1ba493676d9dc77234a8dbfcd07ae", [:mix], [{:igniter, ">= 0.2.6 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.2", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "143d3f78d717556041a1b89f523ba7f3004f90351a567e9ea9044f90afcd1085"},
4343
"spitfire": {:hex, :spitfire, "0.1.3", "7ea0f544005dfbe48e615ed90250c9a271bfe126914012023fd5e4b6b82b7ec7", [:mix], [], "hexpm", "d53b5107bcff526a05c5bb54c95e77b36834550affd5830c9f58760e8c543657"},
4444
"splode": {:hex, :splode, "0.2.4", "71046334c39605095ca4bed5d008372e56454060997da14f9868534c17b84b53", [:mix], [], "hexpm", "ca3b95f0d8d4b482b5357954fec857abd0fa3ea509d623334c1328e7382044c2"},
4545
"statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},

test/aggregate_test.exs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,6 @@ defmodule AshSql.AggregateTest do
345345
|> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove)
346346
|> Ash.create!()
347347

348-
Logger.configure(level: :debug)
349-
350348
assert Comment
351349
|> Ash.Query.filter(post.has_comment_called_match)
352350
|> Ash.read_one!()

test/support/test_repo.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ defmodule AshPostgres.TestRepo do
1212
Application.get_env(:ash_postgres, :no_extensions, [])
1313
end
1414

15+
def min_pg_version do
16+
%Version{major: 16, minor: 0, patch: 0}
17+
end
18+
1519
def all_tenants do
1620
Code.ensure_compiled(AshPostgres.MultitenancyTest.Org)
1721

0 commit comments

Comments
 (0)