-
-
Notifications
You must be signed in to change notification settings - Fork 28
Description
I think that the following may just be a very strong warning in the documentation as I can't actually think of a sane way of fixing it, though your mileage may vary.
Consider some code that does something like:
red-do {
# do something to DB
start {
# do something to do DB
};
# do something to DB
}, :transaction;
With the Pg driver, the #504 essentially isolates a transaction from other concurrent access outside the transaction by creating a new instance of DB::Pg with its own connection pool such that as long as all access in the transaction is performed sequentially then all will get the same underlying connection from the pool.
However if some code is started asynchronously as above, the async code will get the existing DB::Pg::Database instance (assumed to be the one that the transaction was started on,) at which point it essentially becomes a race between the async code, any DB code after it is started and crucially the COMMIT (or ROLLBACK ) which may get a different connection from the pool such that the code after may not be in the transaction, or the commit is called on a connection without a transaction (leading to an error.) Obviously it becomes less predictable if more threads are spawned.
The only way to prevent this is by waiting on the async code before any further DB access is done in the main block and especially before the end of the red-do block.
A mitigation could be provided if the async code doesn't need to take part in the main transaction by allowing a red-do to over-ride the behaviour described in #506 and force the creation of a further new driver instance with a new connection. But :-(