Skip to content

Commit 1609c7b

Browse files
committed
allow duplicate keys to handle multi migrations
1 parent be26168 commit 1609c7b

File tree

1 file changed

+59
-63
lines changed

1 file changed

+59
-63
lines changed

scripts/database_migration.exs

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,26 @@ defmodule DatabaseMigration do
3434

3535
require Logger
3636

37-
@schema_mappings %{
38-
"User" => User,
39-
"Org" => User,
40-
"GithubUser" => User,
41-
"Account" => Identity,
42-
"OrgMember" => Member,
43-
"Task" => Ticket,
44-
"GithubIssue" => nil,
45-
"GithubPullRequest" => nil,
46-
"Bounty" => Bounty,
47-
"Reward" => nil,
48-
"Attempt" => Attempt,
49-
"Claim" => Claim,
50-
"BountyCharge" => Transaction,
51-
"BountyTransfer" => Transaction,
52-
"GithubInstallation" => Installation,
53-
"StripeAccount" => Account,
54-
"StripeCustomer" => Customer,
55-
"StripePaymentMethod" => PaymentMethod
56-
}
37+
@schema_mappings [
38+
{"User", User},
39+
{"Org", User},
40+
{"GithubUser", User},
41+
{"Account", Identity},
42+
{"OrgMember", Member},
43+
{"Task", Ticket},
44+
{"GithubIssue", nil},
45+
{"GithubPullRequest", nil},
46+
{"Bounty", Bounty},
47+
{"Reward", nil},
48+
{"Attempt", Attempt},
49+
{"Claim", Claim},
50+
{"BountyCharge", Transaction},
51+
{"BountyTransfer", Transaction},
52+
{"GithubInstallation", Installation},
53+
{"StripeAccount", Account},
54+
{"StripeCustomer", Customer},
55+
{"StripePaymentMethod", PaymentMethod}
56+
]
5757

5858
@backfilled_tables [
5959
"accounts",
@@ -71,9 +71,9 @@ defmodule DatabaseMigration do
7171
"users"
7272
]
7373

74-
@relevant_tables Map.keys(@schema_mappings)
74+
defp relevant_tables, do: @schema_mappings |> Enum.map(fn {k, _v} -> k end) |> Enum.dedup()
7575

76-
defp transform("Task", row, db) do
76+
defp transform({"Task", Ticket}, row, db) do
7777
if row["forge"] != "github" do
7878
raise "Unknown forge: #{row["forge"]}"
7979
end
@@ -133,7 +133,7 @@ defmodule DatabaseMigration do
133133
row
134134
end
135135

136-
defp transform("User", row, db) do
136+
defp transform({"User", User}, row, db) do
137137
# TODO: reenable
138138
# if !row["\"emailVerified\""] || String.length(row["\"emailVerified\""]) < 10 do
139139
# raise "Email not verified: #{inspect(row)}"
@@ -189,7 +189,7 @@ defmodule DatabaseMigration do
189189
}
190190
end
191191

192-
defp transform("Org", row, _db) do
192+
defp transform({"Org", User}, row, _db) do
193193
%{
194194
"id" => row["id"],
195195
"provider" => row["github_handle"] && "github",
@@ -238,7 +238,7 @@ defmodule DatabaseMigration do
238238
}
239239
end
240240

241-
defp transform("GithubUser", %{user_id: nil} = row, _db) do
241+
defp transform({"GithubUser", User}, %{user_id: nil} = row, _db) do
242242
if row["type"] != "User" do
243243
raise "GithubUser is not a User: #{inspect(row)}"
244244
end
@@ -291,9 +291,9 @@ defmodule DatabaseMigration do
291291
}
292292
end
293293

294-
defp transform("GithubUser", _row, _db), do: nil
294+
defp transform({"GithubUser", User}, _row, _db), do: nil
295295

296-
defp transform("Account", row, _db) do
296+
defp transform({"Account", Identity}, row, _db) do
297297
%{
298298
"id" => row["id"],
299299
"user_id" => row["\"userId\""],
@@ -308,7 +308,7 @@ defmodule DatabaseMigration do
308308
}
309309
end
310310

311-
defp transform("OrgMember", row, _db) do
311+
defp transform({"OrgMember", Member}, row, _db) do
312312
%{
313313
"id" => row["id"],
314314
"org_id" => row["org_id"],
@@ -319,7 +319,7 @@ defmodule DatabaseMigration do
319319
}
320320
end
321321

322-
defp transform("Bounty", row, db) do
322+
defp transform({"Bounty", Bounty}, row, db) do
323323
reward = db |> Map.get("Reward", []) |> Enum.find(&(&1["bounty_id"] == row["id"]))
324324

325325
amount = if reward, do: Money.from_integer(String.to_integer(reward["amount"]), reward["currency"])
@@ -335,7 +335,7 @@ defmodule DatabaseMigration do
335335
}
336336
end
337337

338-
defp transform("Attempt", row, db) do
338+
defp transform({"Attempt", Attempt}, row, db) do
339339
bounty = db |> Map.get("Bounty", []) |> Enum.find(&(&1["id"] == row["bounty_id"]))
340340

341341
github_user = db |> Map.get("GithubUser", []) |> Enum.find(&(&1["id"] == row["github_user_id"]))
@@ -361,7 +361,7 @@ defmodule DatabaseMigration do
361361
}
362362
end
363363

364-
defp transform("Claim", row, db) do
364+
defp transform({"Claim", Claim}, row, db) do
365365
bounty = db |> Map.get("Bounty", []) |> Enum.find(&(&1["id"] == row["bounty_id"]))
366366

367367
task = db |> Map.get("Task", []) |> Enum.find(&(&1["id"] == bounty["task_id"]))
@@ -393,7 +393,7 @@ defmodule DatabaseMigration do
393393
}
394394
end
395395

396-
defp transform("BountyCharge", row, db) do
396+
defp transform({"BountyCharge", Transaction}, row, db) do
397397
user = db |> Map.get("Org", []) |> Enum.find(&(&1["id"] == row["org_id"]))
398398

399399
amount = Money.from_integer(String.to_integer(row["amount"]), row["currency"])
@@ -438,7 +438,7 @@ defmodule DatabaseMigration do
438438
}
439439
end
440440

441-
defp transform("BountyTransfer", row, db) do
441+
defp transform({"BountyTransfer", Transaction}, row, db) do
442442
claim = db |> Map.get("Claim", []) |> Enum.find(&(&1["id"] == row["claim_id"]))
443443

444444
github_user = db |> Map.get("GithubUser", []) |> Enum.find(&(&1["id"] == claim["github_user_id"]))
@@ -487,7 +487,7 @@ defmodule DatabaseMigration do
487487
}
488488
end
489489

490-
defp transform("GithubInstallation", row, _db) do
490+
defp transform({"GithubInstallation", Installation}, row, _db) do
491491
%{
492492
"id" => row["id"],
493493
"provider" => "github",
@@ -503,7 +503,7 @@ defmodule DatabaseMigration do
503503
}
504504
end
505505

506-
defp transform("StripeAccount", row, _db) do
506+
defp transform({"StripeAccount", Account}, row, _db) do
507507
%{
508508
"id" => row["id"],
509509
"provider" => "stripe",
@@ -526,7 +526,7 @@ defmodule DatabaseMigration do
526526
}
527527
end
528528

529-
defp transform("StripeCustomer", row, _db) do
529+
defp transform({"StripeCustomer", Customer}, row, _db) do
530530
%{
531531
"id" => row["id"],
532532
"provider" => "stripe",
@@ -539,7 +539,7 @@ defmodule DatabaseMigration do
539539
}
540540
end
541541

542-
defp transform("StripePaymentMethod", row, db) do
542+
defp transform({"StripePaymentMethod", PaymentMethod}, row, db) do
543543
customer = db |> Map.get("StripeCustomer", []) |> Enum.find(&(&1["id"] == row["customer_id"]))
544544

545545
if !customer do
@@ -586,12 +586,13 @@ defmodule DatabaseMigration do
586586
&collect_after_fun/1
587587
)
588588
|> Enum.reduce(%{}, fn
589-
{table, data}, acc when table in @relevant_tables ->
590-
parsed_data = parse_copy_data(data)
591-
Map.put(acc, table, parsed_data)
592-
593-
_, acc ->
594-
acc
589+
{table, data}, acc ->
590+
if table in relevant_tables() do
591+
parsed_data = parse_copy_data(data)
592+
Map.put(acc, table, parsed_data)
593+
else
594+
acc
595+
end
595596
end)
596597
end
597598

@@ -628,24 +629,25 @@ defmodule DatabaseMigration do
628629
defp collect_after_fun({table, acc}), do: {:cont, {table, Enum.reverse(acc)}, nil}
629630

630631
defp process_chunk(chunk, db) do
631-
case_result =
632-
case extract_copy_section(chunk) do
633-
%{table: table} = section when table in @relevant_tables ->
634-
transform_section(section, db)
635-
636-
_ ->
637-
nil
638-
end
632+
case extract_copy_section(chunk) do
633+
%{table: table} = section ->
634+
@schema_mappings
635+
|> Enum.filter(fn {k, _v} -> k == table end)
636+
|> Enum.map(fn {_k, v} -> transform_section(section, v, db) end)
637+
|> Enum.reject(&is_nil/1)
638+
|> Enum.map(&load_copy_section/1)
639639

640-
load_copy_section(case_result)
640+
_ ->
641+
[]
642+
end
641643
end
642644

643-
defp transform_section(%{table: table, columns: _columns, data: data}, db) do
645+
defp transform_section(%{table: table, columns: _columns, data: data}, schema, db) do
644646
transformed_data =
645647
data
646648
|> Enum.map(fn row ->
647649
# try do
648-
transform(table, row, db)
650+
transform({table, schema}, row, db)
649651
# rescue
650652
# e ->
651653
# IO.puts("Error transforming row in table #{table}: #{inspect(row)}")
@@ -654,9 +656,9 @@ defmodule DatabaseMigration do
654656
# end
655657
end)
656658
|> Enum.reject(&is_nil/1)
657-
|> Enum.map(&post_transform(table, &1))
659+
|> Enum.map(&post_transform(schema, &1))
658660

659-
transformed_table_name = transform_table_name(table)
661+
transformed_table_name = schema.__schema__(:source)
660662

661663
if Enum.empty?(transformed_data) do
662664
nil
@@ -666,11 +668,7 @@ defmodule DatabaseMigration do
666668
end
667669
end
668670

669-
defp transform_table_name(table_name), do: if(schema = @schema_mappings[table_name], do: schema.__schema__(:source))
670-
671-
defp post_transform(table_name, row) do
672-
schema = @schema_mappings[table_name]
673-
671+
defp post_transform(schema, row) do
674672
default_fields =
675673
schema.__struct__()
676674
|> Map.from_struct()
@@ -732,8 +730,6 @@ defmodule DatabaseMigration do
732730
new_handle
733731
end
734732

735-
defp load_copy_section(nil), do: []
736-
737733
defp load_copy_section(%{table: table_name, columns: columns, data: data}) do
738734
copy_statement = "COPY #{table_name} (#{Enum.join(columns, ", ")}) FROM stdin;\n"
739735

0 commit comments

Comments
 (0)