Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argument error on :ets.lookup(:tzdata_current_release, :release_version) when running inside migration

I have this piece of code:

case Timex.Timezone.get(data) do
  {:error, _} = error ->
    error

  data ->
    {:ok, data}
end

to put timezones that are saved in the database into a struct.

Well when running a migration that gets some data through an Ecto Query I get this error:

** (ArgumentError) argument error
    (stdlib) :ets.lookup(:tzdata_current_release, :release_version)
    lib/tzdata/release_reader.ex:47: Tzdata.ReleaseReader.current_release_from_table/0
    lib/tzdata/release_reader.ex:14: Tzdata.ReleaseReader.simple_lookup/1
    lib/tzdata/release_reader.ex:7: Tzdata.ReleaseReader.zone_and_link_list/0
    lib/tzdata.ex:40: Tzdata.zone_exists?/1
    lib/timezone/timezone.ex:152: Timex.Timezone.name_of/1
    lib/timezone/timezone.ex:180: Timex.Timezone.get/2
    lib/common/ecto/timezone.ex:27: Common.Ecto.Timezone.load/1
    (ecto) lib/ecto/type.ex:661: Ecto.Type.process_loaders/3
    (ecto) lib/ecto/schema.ex:1490: Ecto.Schema.load!/5
    (ecto) lib/ecto/schema.ex:1442: Ecto.Schema.safe_load_zip/4
    (ecto) lib/ecto/schema.ex:1443: Ecto.Schema.safe_load_zip/4
    (ecto) lib/ecto/schema.ex:1430: Ecto.Schema.__safe_load__/6
    (ecto) lib/ecto/repo/queryable.ex:282: Ecto.Repo.Queryable.process_source/6
    (ecto) lib/ecto/repo/queryable.ex:170: Ecto.Repo.Queryable.preprocess/5
    (postgrex) lib/postgrex/query.ex:77: DBConnection.Query.Postgrex.Query.decode_map/3
    (postgrex) lib/postgrex/query.ex:64: DBConnection.Query.Postgrex.Query.decode/3
    (db_connection) lib/db_connection.ex:1019: DBConnection.decode/6
    (ecto) lib/ecto/adapters/postgres/connection.ex:73: Ecto.Adapters.Postgres.Connection.prepare_execute/5
    (ecto) lib/ecto/adapters/sql.ex:256: Ecto.Adapters.SQL.sql_call/6

Which has that code in the stack trace and doing some Inspects can verify that that's indeed the call that triggers the error, although doing:

iex(1)> Timex.Timezone.get("America/Los_Angeles")
#<TimezoneInfo(America/Los_Angeles - PDT (-07:00:00))>

In iex -S mix works.

like image 507
Alfonso Embid-Desmet Avatar asked Jul 10 '18 18:07

Alfonso Embid-Desmet


1 Answers

This error happens because Timex needs to be started to function. This is normally done automatically if you add it to your mix.exs dependencies at application startup. However, in mix tasks you have to manually select which applications to start. In your custom mix tasks, you can make sure an application is started via Application.ensure_all_started(:timex).

In your ecto.migrate case, we don't have access to the actual mix task, so we need to be a bit more creative by using mix aliases in your mix.exs file:

  def project do
    [
      ...
      aliases: aliases(),
      ...
    ] 
  end


  defp aliases do
    [
      "ecto.migrate_s": ["ecto.migrate.startup", "ecto.migrate"],
    ]
  end

And a Task ecto.migrate.startup for our Application.ensure_all_started(:timex)

defmodule Mix.Tasks.Ecto.Migrate.Startup do
  use Mix.Task

  def run(args) do
    Mix.shell.info("Starting apps required for ecto.migrate...")
    Application.ensure_all_started(:timex)
  end
end

Now you should be able to run mix ecto.migrate_s which first starts timex and then runs your migrations. (This is not a perfectly clean solution, but I'm not aware of alternatives right now)

like image 77
Jonas Dellinger Avatar answered Nov 04 '22 23:11

Jonas Dellinger