测试上的Ecto 2.0 SQL沙盒错误 [英] Ecto 2.0 SQL Sandbox Error on tests

查看:72
本文介绍了测试上的Ecto 2.0 SQL沙盒错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近将我的phoenix项目升级到了Ecto 2.0.2.我有一些代码使用Task.Supervisor.async_nolink在自己的线程上对数据库进行一些更新.运行测试时出现以下错误(仅在测试中发生)

I recently upgraded my phoenix project to Ecto 2.0.2. I have some code that is using Task.Supervisor.async_nolink to make some updates to the db on its own thread. I am getting the following error when my tests run (only occurs on my tests)

[error] Postgrex.Protocol (#PID<0.XXX.0>) disconnected: **
(DBConnection.ConnectionError) owner #PID<0.XXX.0> exited while 
client #PID<0.XXX.0> is still running with: shutdown

现在,我认为我了解发生了什么:在db事务完成之前,正在重新签入Ecto Sandbox连接池.根据文档(至少是我阅读它们的方式),解决这些问题的方法是使用共享连接池:Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, {:shared, self()}).不幸的是,这是行不通的.

Now I think I understand whats happening: The Ecto Sandbox connection pool is being checked back in before the db transaction is complete. According to the docs (at least the way I read them) the way to get around that stuff is to use a shared connection pool: Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, {:shared, self()}) which I am doing. Unfortunately this is not working.

如何设置测试以免发生此错误?

How do I set up my tests so that this error does not occur?

推荐答案

如果其他任何人遇到此问题,我都会直接从语言作者Jose Valim那里得到答案:

If anyone else encounters this, I got an answer back on this directly from the language author Jose Valim:

是的,您对问题的理解是正确的.之所以发生这种情况,是因为拥有连接的测试过程已经退出,但是Task仍在使用其连接.使用{:shared,self()}不能修复它,因为测试仍然拥有该连接,而只是隐式地共享它.

Yes, your understanding of the issue is correct. It is happening because the test process, the one who owns the connection, has exited but the Task is still using its connection. Using {:shared, self()} does not fix it because the test is still owning the connection, you are just sharing it implicitly.

解决方法是确保测试退出之前任务已完成.这可以通过调用Process.exit(task_pid,:kill)来完成.如果您不知道任务PID,则可以调用Task.Supervisor.which_children(NameOfYourTaskSupervisor)返回所有PID,然后遍历并杀死它们.但是,如果您采用这种方法,则测试将无法同时运行(因为您可能会杀死另一个测试启动的任务).

The way to fix is to guarantee the Task has finished before the test exits. This can be done by calling Process.exit(task_pid, :kill). If you don't know the Task PID, you can call Task.Supervisor.which_children(NameOfYourTaskSupervisor) to return all PIDs which you then traverse and kill them. However, if you do this approach, the test cannot run concurrently (as you may kill tasks started by another test).

这篇关于测试上的Ecto 2.0 SQL沙盒错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆