Bagaimana cara menguji transaksi database async yang diterapkan oleh Elixir.Task?

Saya mencoba memasukkan catatan ke dalam database secara asinkron menggunakan Elixir.Task di pengontrol Phoenix. Pengujian yang mencakup metode pengontrol tersebut, mencatat pengecualian bahwa kesalahan koneksi DB (DBConnection.OwnershipError).

Saya mencoba mengatur pengujian pengontrol sebagai async sehingga mode Ecto.Adapters.SQL.Sandbox akan dibagikan.

Tautan ke implementasi Tugas pengontrol: tautan

Tautan ke pengujian untuk pengontrol: tautan

Catatan:

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: []

person Hassan Gharehhasan Loo    schedule 12.07.2019    source sumber


Jawaban (1)


Saya akan menambahkan penjelasan mengenai perbedaan jawaban asli.
person apelsinka223    schedule 12.07.2019
comment
Menyetel tag Aync sebagai salah tidak memperbaikinya. Saya tidak ingin menggunakan mode manual karena artikelnya juga tidak merekomendasikannya. - person Hassan Gharehhasan Loo; 15.07.2019
comment
Kesalahan dengan tag sama? - person apelsinka223; 15.07.2019
comment
Ya, itu sama saja. - person Hassan Gharehhasan Loo; 17.07.2019
comment
Mungkin tugas tidak memiliki cukup waktu untuk menyelesaikan permintaan, coba tambahkan Process.sleep(1000) dalam pengujian. Cara terbaik adalah mengirim beberapa pesan dari tugas dan assert_receive pesan tersebut dalam pengujian, untuk memastikan bahwa tugas selesai, tetapi tidur juga oke - person apelsinka223; 17.07.2019
comment
Secara umum, menurut saya menambahkan tidur dalam pengujian bukanlah ide yang baik, hal ini membuat pengujian berlangsung lama dan tidak dapat diprediksi. - person Hassan Gharehhasan Loo; 29.07.2019
comment
Apa yang saya lakukan, dalam hal ini, adalah memisahkan tugas, menyuntikkannya berdasarkan ENV dan mengejeknya di test env agar tidak dimasukkan ke dalam database. - person Hassan Gharehhasan Loo; 29.07.2019