Hey all,
On my day job, we have a big elixir mono repo and large test suite. Most of our apps uses mysql as database. Given that ecto sandbox does not support async tests for mysql database. Our test suite takes a long time to complete. Basically, the async: true won’t work because of the way mysql transactions work
Approach we are experimenting
We are trying to work around the issue caused by the mysql transaction by using the database itself as an isolation layer. That is, we create multiple databases in the single MySQL instance, having the same structure and configure each connection to connect a different database. For example, if pool_size is 10, we connect each connection to 10 different databases with the same database structure. Since each connection is isolated by database itself instead of transaction, there won’t be deadlock or any such issues.
We wrote a wrapper for ecto.create
and ecto.migrate
to bring up multiple database for test env. We also made it to run in parallel so that the CI pipeline is fast.
Now we configure a separate database for each connection using configure/1
config :my_app, DummyRepo,
adapter: Ecto.Adapters.MyXQL,
....
hostname: "localhost",
port: 3306,
pool: Ecto.Adapters.SQL.Sandbox,
pool_size: 10,
configure: fn args ->
Keyword.put(args, :database, "dummy_#{args[:pool_index]}") # dummy_1, dummy_2 ... dummy_10
end
Then we switched our tests to async: true
This is working fine, and we are seeing the speedup we were aiming.
The concern here though is that pool_index
is undocumented, and I think it is not meant to be used. But replacing it would be tricky. So I wanted to know if there is any suggestion to handle this better. Perhaps ecto team can help?
Or are you guys following a totally different approach altogether to run MySQL tests in parallel?