Ecto.Adapters.SQL.Sandbox.child_spec/1 is undefined or private

I’m trying to use Commanded with Phoenix to create an eventsourced application. I’ve pieced things together from the conduit repo and the commanded docs but I’m getting a failure and stacktrace when I try to run my tests against my aggregate.

There is quite a bit of configuration, support code, and application code so I’m not sure which of that would be helpful to post here. Once my tests start, I’m getting error message:

** (UndefinedFunctionError) function Ecto.Adapters.SQL.Sandbox.child_spec/1 is undefined or private
     stacktrace:
       Ecto.Adapters.SQL.Sandbox.child_spec({Postgrex.Protocol, [types: Postgrex.DefaultTypes, username: "postgres", password: "password", database: "accounts_test", hostname: "localhost", pool: Ecto.Adapters.SQL.Sandbox, pool_size: 2]})
       (db_connection) lib/db_connection.ex:389: DBConnection.start_link/2
       (accounts) test/support/storage.ex:24: Accounts.Storage.reset_readstore/0
       (accounts) test/support/storage.ex:7: Accounts.Storage.reset!/0
       (ex_unit) lib/ex_unit/on_exit_handler.ex:142: ExUnit.OnExitHandler.exec_callback/1
       (ex_unit) lib/ex_unit/on_exit_handler.ex:128: ExUnit.OnExitHandler.on_exit_runner_loop/0

I’ve looked at db_connection.ex:389 and it’s not calling child_spec/1 so I’m very confused why this is happening. I’ve been trying to debug this for about 4 hours now and I’m at a loss.

The last bit of my code from the stacktrace above:

  defp reset_readstore do
    config = Application.get_env(:accounts, Accounts.Repo)
    {:ok, conn} = Postgrex.start_link(config)

    Postgrex.query!(conn, truncate_readstore_tables(), [])
  end
1 Like

I don’t think you can simply respawn Postgrex under your application supervision tree like you are trying to.

The postgres adapter is managed by Ecto.Adapters.Postgresl (ecto_sql), which is supervised by Ecto.Repo (ecto), which is supervised by you application.

And there is fair amount of config involved to setup the Ecto.Adapters.SQL.Sandbox adapter defined in config/test.exs when running tests.

1 Like

The place where I call reset_readstore is in my data_case.ex file and I stop everything just before I call reset_readstore:

  using do
    quote do
      alias Accounts.Repo

      import Ecto
      import Ecto.Changeset
      import Ecto.Query
      # import Accounts.Factory
      # import Accounts.DataCase
      import Commanded.Assertions.EventAssertions
    end
  end

  setup do
    {:ok, _} = Application.ensure_all_started(:accounts)
    
    on_exit(fn ->
      :ok = Application.stop(:accounts)
      :ok = Application.stop(:commanded)
      :ok = Application.stop(:eventstore)
      Accounts.Storage.reset_readstore()
    end)

    :ok
  end

So my understanding is that everything is shutdown by data_case.ex and then I have to re-open the store in order to cleanup the database tables.

Is there a particular reason you’re trying to cleanup the database tables yourself? The Ecto Sandbox is able to take of that for you (by running tests each in their own transaction, either sync or async). If you relied on the Sandbox to do the cleanup than you should be able to remove a bunch of your test configuration/setup.

2 Likes

Thanks @axelson, that’s really helpful. The cleanup code I have is taken from the commanded docs and I found similar code in the conduit repo that I am basing my app off of. If Sandbox can handle that logic for me, so much the better. I’ll give that a try.

2 Likes

@axelson, thanks for the help. Removing my manual cleanup code solved my problem.

2 Likes

I’m glad you got it working! I wonder if it would make sense to submit a PR for that portion of the commanded docs. My guess is that commanded is trying to be database adapter agnostic, but at least a mention of the Ecto Sandbox would probably fit in that section.

@axelson, I had the same thought. I’ll submit something to update the docs. One thing I’ve noticed, setting the pool to Sandbox for eventstore still seems to leave events in the database after my tests complete and seems to be causing some of my tests to fail since the state isn’t getting properly reset between test runs.

I wonder if EventStore doesn’t work properly with Sandbox.

EventStore doesn’t use ecto and therefore cannot be controlled using the ecto sandbox. It uses postgrex directly and therefore needs manual action for cleanup.

2 Likes

@LostKobrakai commanded is v1.0 now but all the example application i see like are using older version of commanded. do you know a sample v1.0 commanded project?

These are pre 1.0


https://leanpub.com/buildingconduit/read

Thanks

1 Like

The GitHub repo for the “Building Conduit” eBook has been updated to use Commanded and EventStore v1.0 if you are still looking.

3 Likes