90 lines
2.8 KiB
Elixir
90 lines
2.8 KiB
Elixir
|
|
# Script for populating the database. You can run it as:
|
||
|
|
#
|
||
|
|
# mix run priv/repo/seeds.exs
|
||
|
|
#
|
||
|
|
# Inside the script, you can read and write to any of your
|
||
|
|
# repositories directly:
|
||
|
|
#
|
||
|
|
# ActionRequestsDemo.Repo.insert!(%ActionRequestsDemo.SomeSchema{})
|
||
|
|
#
|
||
|
|
# We recommend using the bang functions (`insert!`, `update!`
|
||
|
|
# and so on) as they will fail if something goes wrong.
|
||
|
|
|
||
|
|
alias ActionRequestsDemo.Repo
|
||
|
|
alias ActionRequestsDemo.ActionRequests.ActionRequest
|
||
|
|
|
||
|
|
# Configuration
|
||
|
|
total_records = 1_000_000
|
||
|
|
# SQLite has a max parameter limit of 32766
|
||
|
|
# With 7 fields per record, max is ~4681 records per batch
|
||
|
|
# Using 4000 to be safe
|
||
|
|
batch_size = 4_000
|
||
|
|
num_batches = div(total_records, batch_size)
|
||
|
|
|
||
|
|
IO.puts("Seeding #{total_records} action requests in #{num_batches} batches of #{batch_size}...")
|
||
|
|
IO.puts("Started at: #{DateTime.utc_now()}")
|
||
|
|
|
||
|
|
statuses = ["resolved", "unresolved"]
|
||
|
|
|
||
|
|
# Helper function to generate a single record
|
||
|
|
generate_record = fn ->
|
||
|
|
patient_name = Faker.Person.name()
|
||
|
|
status = Enum.random(statuses)
|
||
|
|
assigned_user_id = if :rand.uniform() > 0.3, do: Enum.random(1..5), else: nil
|
||
|
|
days_ago = :rand.uniform(365)
|
||
|
|
|
||
|
|
inserted_at =
|
||
|
|
DateTime.utc_now()
|
||
|
|
|> DateTime.add(-days_ago * 24 * 3600, :second)
|
||
|
|
|> DateTime.truncate(:second)
|
||
|
|
|
||
|
|
delivery_scheduled_at =
|
||
|
|
if :rand.uniform() > 0.4 do
|
||
|
|
days_ahead = :rand.uniform(14)
|
||
|
|
|
||
|
|
NaiveDateTime.utc_now()
|
||
|
|
|> NaiveDateTime.add(days_ahead * 24 * 3600, :second)
|
||
|
|
|> NaiveDateTime.truncate(:second)
|
||
|
|
else
|
||
|
|
nil
|
||
|
|
end
|
||
|
|
|
||
|
|
%{
|
||
|
|
id: Ecto.UUID.generate(),
|
||
|
|
patient_name: patient_name,
|
||
|
|
status: status,
|
||
|
|
assigned_user_id: assigned_user_id,
|
||
|
|
delivery_scheduled_at: delivery_scheduled_at,
|
||
|
|
inserted_at: inserted_at,
|
||
|
|
updated_at: inserted_at
|
||
|
|
}
|
||
|
|
end
|
||
|
|
|
||
|
|
# Process batches sequentially (SQLite doesn't handle concurrent writes well)
|
||
|
|
start_time = System.monotonic_time(:millisecond)
|
||
|
|
|
||
|
|
Enum.each(1..num_batches, fn batch_num ->
|
||
|
|
# Generate batch of records
|
||
|
|
records = for _i <- 1..batch_size, do: generate_record.()
|
||
|
|
|
||
|
|
# Insert batch in a single transaction
|
||
|
|
{count, _} = Repo.insert_all(ActionRequest, records)
|
||
|
|
|
||
|
|
if rem(batch_num, 10) == 0 do
|
||
|
|
elapsed = div(System.monotonic_time(:millisecond) - start_time, 1000)
|
||
|
|
progress = batch_num * batch_size
|
||
|
|
rate = if elapsed > 0, do: div(progress, elapsed), else: 0
|
||
|
|
IO.puts("Progress: #{progress}/#{total_records} (#{div(progress * 100, total_records)}%) - #{rate} records/sec")
|
||
|
|
end
|
||
|
|
|
||
|
|
count
|
||
|
|
end)
|
||
|
|
|
||
|
|
end_time = System.monotonic_time(:millisecond)
|
||
|
|
elapsed_seconds = div(end_time - start_time, 1000)
|
||
|
|
records_per_second = div(total_records, max(elapsed_seconds, 1))
|
||
|
|
|
||
|
|
IO.puts("\n✓ Successfully seeded #{total_records} action requests!")
|
||
|
|
IO.puts("Total time: #{elapsed_seconds} seconds (#{records_per_second} records/sec)")
|
||
|
|
IO.puts("Finished at: #{DateTime.utc_now()}")
|