Closed SimonLab closed 5 years ago
Phoenix 1.4 is using Ecto v3.0 and the following test is failing:
This is due to the new way Ecto is dealing with the precision of the timestamps (see http://blog.plataformatec.com.br/2018/10/a-sneak-peek-at-ecto-3-0-breaking-changes/):
This means that when the get
function is called, the order_by
clause might not return the correct result because the test insert almost at the same time the item and the updated version:
https://github.com/dwyl/phoenix-ecto-append-only-log-example/blob/e8eee00fab8f1555ab93c2d2757c497207d81873/lib/append/append_only_log.ex#L35-L48
I can see two solutions to fix this:
naive_datetime_usec
as describe in the breaking change page and keep the microseconds in the inserted_at
propertytest "get updated item" do
{:ok, item} = insert_address()
Process.sleep(1000)
{:ok, updated_item} = Address.update(item, %{tel: "0123444444"})
assert Address.get(item.entry_id) == updated_item
end
@SimonLab thank you for summarising the Ecto 3.0 changes so others can learn from your research! 😍
While I understand the reasoning behind the breaking change in Ecto to force people to no longer rely on having high-precision time in the database (let's face it: most people don't need microseconds!) I disagree with removing them as it's "dumbing down" elixir to make it more like Ruby or JS. 😞
High precision time is one of Erlang's (and thus Elixir's) best features when it comes to low-latency and we want to have it in our projects so that we can measure latency and database insert volume at a more granular level.
My preference is to use the naive_datetime_usec
type so we capture the more detailed time info.
If it turns out later that we don't need microseconds in our apps, we can always refactor and adopt the Process.sleep(1000)
approach (which feels "dirty" to me).
to recap the process for using the naive_datetime_usec
:
[ ] define the option for the timestamps to use the new type with the schema in lib/append/address.ex
@timestamps_opts [type: :naive_datetime_usec]
schema "addresses" do
field(:entry_id, :string)
field :address_line_1, :string
field :address_line_2, :string
field :city, :string
field :name, :string
field :postcode, :string
field :tel, :string
timestamps()
end
More information about the datetime types in ecto (https://hexdocs.pm/ecto/Ecto.Schema.html#module-the-datetime-types):
[ ] Update the Repo
configuration to define how to handle the timestamps with the migration. In the files config/dev.ex
and config/test.ex
add the line migration_timestamps: [type: :naive_datetime_usec]
. For example the test config looks like this:
# Configure your database
config :append, Append.Repo,
migration_timestamps: [type: :naive_datetime_usec],
username: "append_only",
password: "postgres",
database: "append_test",
hostname: "localhost",
pool: Ecto.Adapters.SQL.Sandbox
naive_datetime
time, you will need to drop the database and run again the migration to make sure the database define the correct format.
you can use the commands mix ecto.drop
and mix ecto.migrate
Readme and code updated with #15
The example is using Phoenix 1.3 at the moment: https://github.com/dwyl/phoenix-ecto-append-only-log-example/blob/e8eee00fab8f1555ab93c2d2757c497207d81873/mix.exs#L39
We can update the Phoenix version to 1.4 and make sure all the steps are still working.
see https://github.com/dwyl/learn-phoenix-framework/issues/118#issue-378671819