Using Custom Timestamps in Migrations

I’ve been working to build an application using Distillery for some time now. I’ve moved to implement release tasks so I can do things like send stats when the application’s booting and run migrations. I haven’t taken it to production yet so this is why I’m noticing this issue now.

My release task looks like this:

defmodule Jacky.ReleaseTasks do
  @start_apps [
    :crypto,
    :ssl,
    :postgrex,
    :timex,
    :timex_ecto,
    :ecto
  ]

  def myapp do
    :jacky
  end

  def repos, do: Application.get_env(myapp(), :ecto_repos, [])

  def seed do
    me = myapp()

    IO.puts("Loading #{me}..")
    # Load the code, but don't start it
    :ok = Application.load(me)

    # Uses Confex to fetch env or locally defined configuration values.
    Jacky.Application.load_runtime_config()

    IO.puts("Starting dependencies..")
    # Start apps necessary for executing migrations
    Enum.each(@start_apps, &Application.load/1)
    Enum.each(@start_apps, &Application.ensure_all_started/1)

    # Start the Repo(s) for myapp
    IO.puts("Starting repos..")
    Enum.each(repos(), & &1.start_link(pool_size: 1))

    # Run migrations
    IO.puts("Running migrations....")
    migrate()
    IO.puts("Migration run.")

    # Run seed script
    Enum.each(repos(), &run_seeds_for/1)

    # Signal shutdown
    IO.puts("Success!")
    :init.stop()
  end

  def migrate, do: Enum.each(repos(), &run_migrations_for/1)

  def priv_dir(app), do: "#{:code.priv_dir(app)}"

  defp run_migrations_for(repo) do
    app = Keyword.get(repo.config, :otp_app)
    IO.puts("Running migrations for #{app}")
    Ecto.Migrator.run(repo, migrations_path(repo), :up, all: true)
  end

  def run_seeds_for(repo) do
    # Run the seed script if it exists
    seed_script = seeds_path(repo)

    if File.exists?(seed_script) do
      IO.puts("Running seed script..")
      Code.eval_file(seed_script)
    end
  end

  def migrations_path(repo), do: priv_path_for(repo, "migrations")

  def seeds_path(repo), do: priv_path_for(repo, "seeds.exs")

  def priv_path_for(repo, filename) do
    app = Keyword.get(repo.config, :otp_app)
    repo_underscore = repo |> Module.split() |> List.last() |> Macro.underscore()
    Path.join([priv_dir(app), repo_underscore, filename])
  end
end

The thing is, when I run this, I get the following:

       ==> Generated sys.config in /app/var
       ==> Generated sys.config in /app/var
       Loading jacky..
       Starting dependencies..
       Starting repos..
       Running migrations....
       Running migrations for jacky
       00:59:50.135 pid=<0.5.0> application=ecto module=Ecto.Migration.Runner function=log/2 file=/opt/jacky/deps/ecto/lib/ecto/migration/runner.ex line=235 [info]  == Running Jacky.Repo.Migrations.CreateTableAccounts.change/0 forward
       {"init terminating in do_boot",{#{'__exception__'=>true,'__struct__'=>'Elixir.ArgumentError',message=><<"Timex.Ecto.DateTime is not a valid database type, please use an atom like :string, :text and so on">>},[{'Elixir.Ecto.Migration','validate_type!',1,[{file,"lib/ecto/migration.ex"},{line,892}]},{'Elixir.Ecto.Migration',add,3,[{file,"lib/ecto/migration.ex"},{line,687}]},{'Elixir.Ecto.Migration',timestamps,1,[{file,"lib/ecto/migration.ex"},{line,750}]},{'Elixir.Jacky.Repo.Migrations.CreateTableAccounts',change,0,[{file,"lib/jacky-0.0.2/priv/repo/migrations/20171026052344_create_table_accounts.exs"},{line,11}]},{timer,tc,3,[{file,"timer.erl"},{line,197}]},{'Elixir.Ecto.Migration.Runner',run,6,[{file,"lib/ecto/migration/runner.ex"},{line,25}]},{'Elixir.Ecto.Migrator',attempt,6,[{file,"lib/ectremote: or.ex"},{line,128}]},{'Elixir.Ecto.Migrator','-do_up/4-fun-1-',4,[{file,"lib/ecto/migrator.ex"},{line,73}]}]}}

I’ve debated just removing Timex.Ecto altogether or somehow wrapping its type under something in my application so it’d get picked up but I wanted to ask on here first.

And I figured it out.

I had a old value for migration timestamps in my config/config.exs. Removing it fixed my problem!

1 Like