So I have a bit of an issue on my application and I don’t know how it is caused. I’m not sure whether my code is fail-safe. I created a table with a context which has an an index on 2 elements but for some reason sometimes the elements are added so I have 2+ elements with the same index so I have an issue.
Here’s my migration file:
defmodule App.Repo.Migrations.CreateCounts do
use Ecto.Migration
def change do
create table(:counts) do
add :date, :string
add :count, :integer
add :owner_id, references(:users, on_delete: :nothing)
timestamps()
end
create index(:counts, [:owner_id, :date])
end
end
And then my count module:
defmodule App.Count do
use Ecto.Schema
import Ecto.Changeset
import Ecto.Query
alias App.Repo
schema "counts" do
field :count, :integer
field :date, :string
field :owner_id, :id
timestamps()
end
def changeset(email_count, attrs) do
email_count
|> cast(attrs, [:date, :count, :owner_id])
|> validate_required([:date, :count, :owner_id])
end
def increment(struct) do
%__MODULE__{struct | count: struct.count + 1}
end
def create_new() do
today = Timex.now
%__MODULE__{date: Timex.format!(today, "{0D}/{0M}/{YYYY}"), count: 0}
end
def set_owner_id(struct, owner) do
%__MODULE__{struct | owner_id: owner.id}
end
def update_count(owner) do
id = owner.id
date_now = Timex.format!(Timex.now, "{0D}/{0M}/{YYYY}")
buffer =
from(e in __MODULE__, where: e.owner_id == ^id, where: e.date == ^date_now)
|> Repo.one()
if buffer != nil do
data = buffer |> increment() |> Map.from_struct()
changeset(buffer, data)
|> Repo.update()
else
data = create_new() |> set_owner_id(owner) |> increment() |> Map.from_struct()
changeset(%__MODULE__{}, data)
|> Repo.insert()
end
end
end
But then sometimes (I am unable to create it at will) I get an error:
%Ecto.MultipleResultsError{
message: "expected at most one result but got 3 in query:\n\nfrom e0 in App.Count,\n where: e0.owner_id == ^1,\n where: e0.date == ^\"10/02/2020\"\n"
}
``
It looks like the indexes are being ignored because it inserts values with the same `owner_id` and `date`?:
[
%App.Count{
meta: #Ecto.Schema.Metadata<:loaded, “counts”>,
count: 1,
date: “10/02/2020”,
id: 14,
inserted_at: ~N[2020-02-10 13:00:11],
owner_id: 1,
updated_at: ~N[2020-02-10 13:00:11]
},
%App.Count{
meta: #Ecto.Schema.Metadata<:loaded, “counts”>,
count: 1,
date: “10/02/2020”,
id: 15,
inserted_at: ~N[2020-02-10 13:00:11],
owner_id: 1,
updated_at: ~N[2020-02-10 13:00:11]
},
%App.Count{
meta: #Ecto.Schema.Metadata<:loaded, “counts”>,
count: 1,
date: “10/02/2020”,
id: 16,
inserted_at: ~N[2020-02-10 13:00:11],
owner_id: 1,
updated_at: ~N[2020-02-10 13:00:11]
}
]```