Giter Site home page Giter Site logo

Comments (9)

michalmuskala avatar michalmuskala commented on June 27, 2024

In general, transactions cannot span across processes - either during tests with sandbox or regular operation. We could potentially improve the error here, though.

from ecto_sql.

dkulchenko avatar dkulchenko commented on June 27, 2024

That makes sense, but in this case I'm not intending for the outer transaction to be reused in the task process - it's meant to be its own stream of work (and if I understand correctly, this is what happens running the same code in a non-test environment, the task would check out a separate connection).

But spawning that task from within an open transaction during a test prevents it from executing at all, which doesn't seem right.

The example above is simplified to the minimum to trigger the error - in my real project, the outer transaction is doing its own work and happens to spawn a few tasks as well. This works fine in dev, but in test, the above happens.

from ecto_sql.

josevalim avatar josevalim commented on June 27, 2024

@dkulchenko when using the sandbox, the connections are either explicitly assigned or shared. So one of two things will happen in your tasks:

  1. You have a single connection, which you are trying to use across all processes, which causes it to fail

  2. The task does not have a connection assigned to it, which causes it to fail

We added automatically sharing for tasks in a sandbox in recent versions, which means you are triggering 1. But without 1, you would just trigger 2.

from ecto_sql.

josevalim avatar josevalim commented on June 27, 2024

In any case, here is a PR that improves the error message in this case: elixir-ecto/db_connection#200

from ecto_sql.

josevalim avatar josevalim commented on June 27, 2024

Closing in favor of the PR above. :)

from ecto_sql.

dkulchenko avatar dkulchenko commented on June 27, 2024

@josevalim Understood - thank you for the explanation :) Will rewrite things a bit so that the one shared connection can be used.

from ecto_sql.

igsp7 avatar igsp7 commented on June 27, 2024

I am facing the exact same situation. @dkulchenko how did you manage to make your Tasks use the shared connection?

from ecto_sql.

dkulchenko avatar dkulchenko commented on June 27, 2024

I pulled up the old project that I ran into this with and it looks like my solution was to untangle the cyclic dependency.

Basically, the test case above hangs because the async task is trying to use the sandbox connection, but the parent task has it checked out for the transaction and can't release it (because the transaction call itself is blocking on the async task completing).

The real world case I was encountering this in was calling an audit function that needed to (in the background) add some auditing rows to the DB (and this function was itself called from within a parent transaction). I ended up moving the auditing code to run in a Task.Supervisor and not blocking on the call inside the parent transaction.

I also added some "real" DB tests that run against a test DB with sandbox mode disabled and exercise the code using the normal path.

Looking through the old code, it looks like my approaches were essentially to have a wrapper MyProject.Tasks module that selectively inlined async tasks in test (to not spawn a separate task at all) or to untangle dependencies using non-blocking/non-immediately-awaited tasks, keeping in mind there's only one connection available at a time in the test sandbox. This can be supplemented with non-sandboxed tests as needed to fill in any coverage gaps.

This was really early in my Elixir learning so it's possible that newer releases of Ecto have mitigated this in other ways, or perhaps there's better approaches.

from ecto_sql.

igsp7 avatar igsp7 commented on June 27, 2024

Thank you very much for the detailed explanation @dkulchenko

from ecto_sql.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.