我正在尝试使用 Phoenix 控制器中的Elixir.Task
异步插入数据库中的记录。涵盖该控制器方法的测试记录数据库连接错误 (DBConnection.OwnershipError( 的异常。
我尝试将控制器测试设置为异步,以便共享 Ecto.Adapters.SQL.Sandbox 模式。
链接到控制器 任务实现:链接
控制器测试链接:链接
日志:
05:28:21.325 [error] Task #PID<0.438.0> started from #PID<0.436.0> terminating
** (DBConnection.OwnershipError) cannot find ownership process for #PID<0.438.0>.
When using ownership, you must manage connections in one
of the four ways:
* By explicitly checking out a connection
* By explicitly allowing a spawned process
* By running the pool in shared mode
* By using :caller option with allowed process
The first two options require every new process to explicitly
check a connection out or be allowed by calling checkout or
allow respectively.
The third option requires a {:shared, pid} mode to be set.
If using shared mode in tests, make sure your tests are not
async.
The fourth option requires [caller: pid] to be used when
checking out a connection from the pool. The caller process
should already be allowed on a connection.
If you are reading this error, it means you have not done one
of the steps above or that the owner process has crashed.
See Ecto.Adapters.SQL.Sandbox docs for more information.
(ecto_sql) lib/ecto/adapters/sql.ex:618: Ecto.Adapters.SQL.raise_sql_call_error/1
(ecto) lib/ecto/repo/schema.ex:649: Ecto.Repo.Schema.apply/4
(ecto) lib/ecto/repo/schema.ex:262: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
(elixir) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Function: #Function<4.97600206/0 in UrlShortenerWeb.LinkController.redirect_url/2>
Args: []
05:28:21.380 [error] Task #PID<0.435.0> started from #PID<0.433.0> terminating
** (stop) exited in: DBConnection.Holder.checkout(#PID<0.434.0>, [log: #Function<11.104730475/1 in Ecto.Adapters.SQL.with_log/3>, cache_statement: "ecto_insert_visits", timeout: 15000, pool_size: 10, pool: DBConnection.Ownership])
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(db_connection) lib/db_connection/holder.ex:71: DBConnection.Holder.checkout/2
(db_connection) lib/db_connection.ex:1030: DBConnection.checkout/3
(db_connection) lib/db_connection.ex:1340: DBConnection.run/6
(db_connection) lib/db_connection.ex:540: DBConnection.parsed_prepare_execute/5
(db_connection) lib/db_connection.ex:533: DBConnection.prepare_execute/4
(postgrex) lib/postgrex.ex:196: Postgrex.query/4
(ecto_sql) lib/ecto/adapters/sql.ex:658: Ecto.Adapters.SQL.struct/10
(ecto) lib/ecto/repo/schema.ex:649: Ecto.Repo.Schema.apply/4
(ecto) lib/ecto/repo/schema.ex:262: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
(elixir) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Function: #Function<4.97600206/0 in UrlShortenerWeb.LinkController.redirect_url/2>
Args: []
05:28:21.380 [error] Task #PID<0.441.0> started from #PID<0.439.0> terminating
** (stop) exited in: DBConnection.Holder.checkout(#PID<0.440.0>, [log: #Function<11.104730475/1 in Ecto.Adapters.SQL.with_log/3>, cache_statement: "ecto_insert_visits", timeout: 15000, pool_size: 10, pool: DBConnection.Ownership])
** (EXIT) shutdown: "owner #PID<0.439.0> exited"
(db_connection) lib/db_connection/holder.ex:71: DBConnection.Holder.checkout/2
(db_connection) lib/db_connection.ex:1030: DBConnection.checkout/3
(db_connection) lib/db_connection.ex:1340: DBConnection.run/6
(db_connection) lib/db_connection.ex:540: DBConnection.parsed_prepare_execute/5
(db_connection) lib/db_connection.ex:533: DBConnection.prepare_execute/4
(postgrex) lib/postgrex.ex:196: Postgrex.query/4
(ecto_sql) lib/ecto/adapters/sql.ex:658: Ecto.Adapters.SQL.struct/10
(ecto) lib/ecto/repo/schema.ex:649: Ecto.Repo.Schema.apply/4
(ecto) lib/ecto/repo/schema.ex:262: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
(elixir) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Function: #Function<4.97600206/0 in UrlShortenerWeb.LinkController.redirect_url/2>
Args: []
您需要
在测试中使用字符串中添加标签
use UrlShortenerWeb.ConnCase, async: false
这将在测试用例中运行此行,这将为所有进程提供数据库连接的所有权,测试也将同步运行。
另一种更复杂的方法 - 使用手动模式并允许进程使用连接。
这篇文章对所有权模式有一个很好的解释