Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit71577c9

Browse files
committed
fix: tenant migrations should honor module attributes
such as @disable_ddl_transaction and @disable_migration_lock
1 parent913f936 commit71577c9

File tree

5 files changed

+272
-4
lines changed

5 files changed

+272
-4
lines changed

‎lib/migration_generator/migration_generator.ex‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,14 @@ defmodule AshPostgres.MigrationGenerator do
555555
versioninversions
556556
end)
557557
|>Enum.each(fn{version,mod}->
558+
runner_opts=
559+
[
560+
all:true,
561+
prefix:prefix
562+
]
563+
|>maybe_put_mod_attribute(mod,:disable_ddl_transaction)
564+
|>maybe_put_mod_attribute(mod,:disable_migration_lock)
565+
558566
Ecto.Migration.Runner.run(
559567
repo,
560568
[],
@@ -563,8 +571,7 @@ defmodule AshPostgres.MigrationGenerator do
563571
:forward,
564572
:down,
565573
:down,
566-
all:true,
567-
prefix:prefix
574+
runner_opts
568575
)
569576

570577
Ecto.Migration.SchemaMigration.down(repo,repo.config(),version,prefix:prefix)
@@ -3858,4 +3865,14 @@ defmodule AshPostgres.MigrationGenerator do
38583865

38593866
defpto_ordered_object(value)whenis_list(value),do:Enum.map(value,&to_ordered_object/1)
38603867
defpto_ordered_object(value),do:value
3868+
3869+
defpmaybe_put_mod_attribute(opts,mod,attribute)do
3870+
migration_config=mod.__migration__()
3871+
3872+
casemigration_config[attribute]do
3873+
nil->opts
3874+
false->opts
3875+
value->Keyword.put(opts,attribute,value)
3876+
end
3877+
end
38613878
end

‎lib/multitenancy.ex‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ defmodule AshPostgres.MultiTenancy do
4646
|>Enum.filter(&&1)
4747
|>Enum.map(&load_migration!/1)
4848
|>Enum.each(fn{version,mod}->
49+
runner_opts=
50+
[
51+
all:true,
52+
prefix:tenant_name
53+
]
54+
|>maybe_put_mod_attribute(mod,:disable_ddl_transaction)
55+
|>maybe_put_mod_attribute(mod,:disable_migration_lock)
56+
4957
Ecto.Migration.Runner.run(
5058
repo,
5159
[],
@@ -54,8 +62,7 @@ defmodule AshPostgres.MultiTenancy do
5462
:forward,
5563
:up,
5664
:up,
57-
all:true,
58-
prefix:tenant_name
65+
runner_opts
5966
)
6067

6168
Ecto.Migration.SchemaMigration.up(repo,repo.config(),version,prefix:tenant_name)
@@ -121,4 +128,14 @@ defmodule AshPostgres.MultiTenancy do
121128
defptenant_name_regexdo
122129
~r/^[a-zA-Z0-9_-]+$/
123130
end
131+
132+
defpmaybe_put_mod_attribute(opts,mod,attribute)do
133+
migration_config=mod.__migration__()
134+
135+
casemigration_config[attribute]do
136+
nil->opts
137+
false->opts
138+
value->Keyword.put(opts,attribute,value)
139+
end
140+
end
124141
end
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# SPDX-FileCopyrightText: 2019 ash_postgres contributors <https://github.com/ash-project/ash_postgres/graphs.contributors>
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
defmoduleAshPostgres.MigrationModuleAttributesNoSandboxTestdo
6+
useAshPostgres.RepoNoSandboxCase,async:false
7+
@moduletag:migration
8+
9+
importExUnit.CaptureLog
10+
11+
setupdo
12+
timestamp=DateTime.utc_now()|>DateTime.to_unix(:microsecond)
13+
unique_id=System.unique_integer([:positive])
14+
tenant_name="test_no_sandbox_tenant_#{timestamp}_#{unique_id}"
15+
16+
Ecto.Adapters.SQL.query!(
17+
AshPostgres.TestRepo,
18+
"CREATE SCHEMA IF NOT EXISTS\"#{tenant_name}\"",
19+
[]
20+
)
21+
22+
Ecto.Adapters.SQL.query!(
23+
AshPostgres.TestRepo,
24+
"CREATE TABLE\"#{tenant_name}\".posts (id serial PRIMARY KEY, title text)",
25+
[]
26+
)
27+
28+
on_exit(fn->
29+
Ecto.Adapters.SQL.query!(AshPostgres.TestRepo,"DROP SCHEMA\"#{tenant_name}\" CASCADE",[])
30+
end)
31+
32+
%{tenant_name:tenant_name}
33+
end
34+
35+
describe"migration attributes without sandbox"do
36+
test"tenant migration with @disable_ddl_transaction can create concurrent index",%{
37+
tenant_name:tenant_name
38+
}do
39+
migration_content="""
40+
defmodule TestConcurrentIndexMigrationNoSandbox do
41+
use Ecto.Migration
42+
@disable_ddl_transaction true
43+
@disable_migration_lock true
44+
45+
def up do
46+
create index(:posts, [:title], concurrently: true)
47+
end
48+
49+
def down do
50+
drop index(:posts, [:title])
51+
end
52+
end
53+
"""
54+
55+
IO.puts(
56+
"You should not not see a warning in this test about missing @disable_ddl_transaction"
57+
)
58+
59+
migration_file=
60+
create_test_migration("test_concurrent_index_migration_no_sandbox.exs",migration_content)
61+
62+
result=
63+
capture_log(fn->
64+
AshPostgres.MultiTenancy.migrate_tenant(
65+
tenant_name,
66+
AshPostgres.TestRepo,
67+
Path.dirname(migration_file)
68+
)
69+
end)
70+
71+
IO.inspect(result,label:"result")
72+
73+
assertresult=~"== Migrated"
74+
75+
index_result=
76+
Ecto.Adapters.SQL.query!(
77+
AshPostgres.TestRepo,
78+
"""
79+
SELECT indexname FROM pg_indexes
80+
WHERE schemaname = '#{tenant_name}'
81+
AND tablename = 'posts'
82+
AND indexname LIKE '%title%'
83+
""",
84+
[]
85+
)
86+
87+
assertlength(index_result.rows)>0
88+
89+
cleanup_migration_files(migration_file)
90+
end
91+
92+
test"tenant migration without @disable_ddl_transaction gives warnings",%{
93+
tenant_name:tenant_name
94+
}do
95+
migration_content="""
96+
defmodule TestConcurrentIndexMigrationWithoutDisableNoSandbox do
97+
use Ecto.Migration
98+
99+
def up do
100+
create index(:posts, [:title], concurrently: true)
101+
end
102+
103+
def down do
104+
drop index(:posts, [:title])
105+
end
106+
end
107+
"""
108+
109+
IO.puts("You should see a warning in this test about missing @disable_ddl_transaction")
110+
111+
migration_file=
112+
create_test_migration(
113+
"test_concurrent_index_migration_without_disable_no_sandbox.exs",
114+
migration_content
115+
)
116+
117+
result=
118+
capture_log(fn->
119+
AshPostgres.MultiTenancy.migrate_tenant(
120+
tenant_name,
121+
AshPostgres.TestRepo,
122+
Path.dirname(migration_file)
123+
)
124+
end)
125+
126+
IO.inspect(result,label:"result")
127+
# The warnings are printed to the console (visible in test output above)
128+
# We can see them in the test output, but they're not captured by capture_log
129+
# The important thing is that the migration succeeds despite the warnings
130+
assertresult=~"== Migrated"
131+
132+
index_result=
133+
Ecto.Adapters.SQL.query!(
134+
AshPostgres.TestRepo,
135+
"""
136+
SELECT indexname FROM pg_indexes
137+
WHERE schemaname = '#{tenant_name}'
138+
AND tablename = 'posts'
139+
AND indexname LIKE '%title%'
140+
""",
141+
[]
142+
)
143+
144+
assertlength(index_result.rows)>0
145+
146+
cleanup_migration_files(migration_file)
147+
end
148+
end
149+
150+
defpcreate_test_migration(filename,content)do
151+
# Create a unique directory for this specific test run
152+
timestamp=DateTime.utc_now()|>DateTime.to_unix(:microsecond)|>Integer.to_string()
153+
unique_id=System.unique_integer([:positive])
154+
155+
test_migrations_dir=
156+
Path.join(System.tmp_dir!(),"ash_postgres_test_migrations_#{timestamp}_#{unique_id}")
157+
158+
File.mkdir_p!(test_migrations_dir)
159+
160+
migration_filename="#{timestamp}_#{filename}"
161+
migration_file=Path.join(test_migrations_dir,migration_filename)
162+
File.write!(migration_file,content)
163+
164+
# Don't compile the file here - let the migration system handle it
165+
migration_file
166+
end
167+
168+
defpcleanup_migration_files(migration_file)do
169+
migration_dir=Path.dirname(migration_file)
170+
File.rm_rf(migration_dir)
171+
end
172+
end

‎test/support/no_sandbox_case.ex‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# SPDX-FileCopyrightText: 2019 ash_postgres contributors <https://github.com/ash-project/ash_postgres/graphs.contributors>
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
defmoduleAshPostgres.RepoNoSandboxCasedo
6+
@moduledoc"""
7+
Test case for testing database operations without sandbox transaction wrapping.
8+
9+
This is useful for testing operations that cannot run inside transactions,
10+
such as concurrent index creation with @disable_ddl_transaction.
11+
"""
12+
useExUnit.CaseTemplate
13+
14+
usingdo
15+
quotedo
16+
aliasAshPostgres.TestRepo
17+
18+
importEcto
19+
importEcto.Query
20+
importAshPostgres.RepoNoSandboxCase
21+
22+
# and any other stuff
23+
end
24+
end
25+
26+
setup_tagsdo
27+
# No sandbox setup - just ensure the repo is available
28+
# This allows testing operations that cannot run in transactions
29+
:ok
30+
end
31+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# SPDX-FileCopyrightText: 2019 ash_postgres contributors <https://github.com/ash-project/ash_postgres/graphs.contributors>
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
defmoduleAshPostgres.RepoNoSandboxCasedo
6+
@moduledoc"""
7+
Test case for testing database operations without sandbox transaction wrapping.
8+
9+
This is useful for testing operations that cannot run inside transactions,
10+
such as concurrent index creation with @disable_ddl_transaction.
11+
"""
12+
useExUnit.CaseTemplate
13+
14+
usingdo
15+
quotedo
16+
aliasAshPostgres.TestRepo
17+
18+
importEcto
19+
importEcto.Query
20+
importAshPostgres.RepoNoSandboxCase
21+
22+
# and any other stuff
23+
end
24+
end
25+
26+
setup_tagsdo
27+
# No sandbox setup - just ensure the repo is available
28+
# This allows testing operations that cannot run in transactions
29+
:ok
30+
end
31+
end

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp