add preseem sync logs schema and migration
This commit is contained in:
parent
5f17d5aed1
commit
26e19b00f7
3 changed files with 151 additions and 0 deletions
41
lib/towerops/preseem/sync_log.ex
Normal file
41
lib/towerops/preseem/sync_log.ex
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
defmodule Towerops.Preseem.SyncLog do
|
||||
@moduledoc """
|
||||
Audit log for Preseem sync operations.
|
||||
"""
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
|
||||
@valid_statuses ~w(success partial failed)
|
||||
|
||||
schema "preseem_sync_logs" do
|
||||
field :status, :string
|
||||
field :records_synced, :integer, default: 0
|
||||
field :errors, :map
|
||||
field :duration_ms, :integer
|
||||
field :inserted_at, :utc_datetime
|
||||
|
||||
belongs_to :organization, Towerops.Organizations.Organization
|
||||
belongs_to :integration, Towerops.Integrations.Integration
|
||||
end
|
||||
|
||||
def changeset(sync_log, attrs) do
|
||||
sync_log
|
||||
|> cast(attrs, [
|
||||
:organization_id,
|
||||
:integration_id,
|
||||
:status,
|
||||
:records_synced,
|
||||
:errors,
|
||||
:duration_ms,
|
||||
:inserted_at
|
||||
])
|
||||
|> validate_required([:organization_id, :integration_id, :status, :inserted_at])
|
||||
|> validate_inclusion(:status, @valid_statuses)
|
||||
|> foreign_key_constraint(:organization_id)
|
||||
|> foreign_key_constraint(:integration_id)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
defmodule Towerops.Repo.Migrations.CreatePreseemSyncLogs do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table(:preseem_sync_logs, primary_key: false) do
|
||||
add :id, :binary_id, primary_key: true
|
||||
|
||||
add :organization_id, references(:organizations, type: :binary_id, on_delete: :delete_all),
|
||||
null: false
|
||||
|
||||
add :integration_id, references(:integrations, type: :binary_id, on_delete: :delete_all),
|
||||
null: false
|
||||
|
||||
add :status, :string, null: false
|
||||
add :records_synced, :integer, default: 0
|
||||
add :errors, :map
|
||||
add :duration_ms, :integer
|
||||
|
||||
add :inserted_at, :utc_datetime, null: false
|
||||
end
|
||||
|
||||
create index(:preseem_sync_logs, [:organization_id])
|
||||
create index(:preseem_sync_logs, [:integration_id])
|
||||
create index(:preseem_sync_logs, [:inserted_at])
|
||||
end
|
||||
end
|
||||
84
test/towerops/preseem/sync_log_test.exs
Normal file
84
test/towerops/preseem/sync_log_test.exs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
defmodule Towerops.Preseem.SyncLogTest do
|
||||
use Towerops.DataCase, async: true
|
||||
|
||||
import Towerops.AccountsFixtures
|
||||
import Towerops.IntegrationsFixtures
|
||||
import Towerops.OrganizationsFixtures
|
||||
|
||||
alias Towerops.Preseem.SyncLog
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
org = organization_fixture(user.id)
|
||||
integration = integration_fixture(org.id)
|
||||
%{organization: org, integration: integration}
|
||||
end
|
||||
|
||||
describe "changeset/2" do
|
||||
test "valid changeset", %{organization: org, integration: integration} do
|
||||
attrs = %{
|
||||
organization_id: org.id,
|
||||
integration_id: integration.id,
|
||||
status: "success",
|
||||
records_synced: 42,
|
||||
duration_ms: 1500,
|
||||
inserted_at: DateTime.truncate(DateTime.utc_now(), :second)
|
||||
}
|
||||
|
||||
changeset = SyncLog.changeset(%SyncLog{}, attrs)
|
||||
assert changeset.valid?
|
||||
end
|
||||
|
||||
test "requires organization_id and integration_id" do
|
||||
attrs = %{status: "success", inserted_at: DateTime.truncate(DateTime.utc_now(), :second)}
|
||||
changeset = SyncLog.changeset(%SyncLog{}, attrs)
|
||||
refute changeset.valid?
|
||||
assert "can't be blank" in errors_on(changeset).organization_id
|
||||
assert "can't be blank" in errors_on(changeset).integration_id
|
||||
end
|
||||
|
||||
test "requires status" do
|
||||
attrs = %{
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
integration_id: Ecto.UUID.generate(),
|
||||
inserted_at: DateTime.truncate(DateTime.utc_now(), :second)
|
||||
}
|
||||
|
||||
changeset = SyncLog.changeset(%SyncLog{}, attrs)
|
||||
refute changeset.valid?
|
||||
assert "can't be blank" in errors_on(changeset).status
|
||||
end
|
||||
|
||||
test "validates status values" do
|
||||
base = %{
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
integration_id: Ecto.UUID.generate(),
|
||||
inserted_at: DateTime.truncate(DateTime.utc_now(), :second)
|
||||
}
|
||||
|
||||
for status <- ~w(success partial failed) do
|
||||
changeset = SyncLog.changeset(%SyncLog{}, Map.put(base, :status, status))
|
||||
assert changeset.valid?, "Expected #{status} to be valid"
|
||||
end
|
||||
|
||||
changeset = SyncLog.changeset(%SyncLog{}, Map.put(base, :status, "bogus"))
|
||||
refute changeset.valid?
|
||||
end
|
||||
|
||||
test "stores error details", %{organization: org, integration: integration} do
|
||||
errors = %{"message" => "API timeout", "code" => 504}
|
||||
|
||||
attrs = %{
|
||||
organization_id: org.id,
|
||||
integration_id: integration.id,
|
||||
status: "failed",
|
||||
errors: errors,
|
||||
inserted_at: DateTime.truncate(DateTime.utc_now(), :second)
|
||||
}
|
||||
|
||||
{:ok, log} = %SyncLog{} |> SyncLog.changeset(attrs) |> Repo.insert()
|
||||
reloaded = Repo.get!(SyncLog, log.id)
|
||||
assert reloaded.errors == errors
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue