-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pgapp:with_transaction() does not work as expected #22
Comments
Ah, now I see. There is a trick:
But the trick only does its work when you do not specify PoolName explicitly.
But this doesn't:
|
I think @edhollandAL wrote some of this code - have time to take a look? |
Just made a fix for the issue. Please have a look. |
Thinking out loud: rather than using the process dictionary, is there a way to, say, pass the |
@lukyanov it's intended behaviour, You shouldn't be able to specify pgapp:with_transaction(pool1, fun() ->
pgapp:squery(pool1, "update ..."),
pgapp:squery(pool1, "delete from ..."),
pgapp:equery(pool1, "select ? from ?", ["*", Table])
end). Functions inside I agree that README is not comprehensive enough and I suggest that it should be fixed instead of current behaviour. |
Ok, I see now. But then I would agree with @davidw that passing
doing_stuff1() ->
pgapp:with_transaction(pool1, fun() ->
pgapp:squery("update ..."),
doing_stuff2()
end).
doing_stuff2() ->
pgapp:with_transaction(pool1, fun() ->
pgapp:squery("update ..."),
end). You will need explicit communication about the connection you are using. |
New variant of the changes: #23 |
@lukyanov: postgres does not have true subtransactions feature - so the example code you show would not work as intended anyway |
I like the new code without the process dictionary - it feels cleaner in any case. Other thoughts? |
I made another PR which is an alternative for #23: #24 @davidw While I agree with you that operating directly with the connection looks clearer and more comprehensible, using kind of 'dirty' approach with process dictionary has the following advantages:
|
Thanks for the updated PR @lukyanov, I agree that the benefits you cite above are important and should be maintained. The If we allow this it is possible (likely) a user will attempt to create some sort of distributed transaction mechanism on top of pgapp; without proper two phase commit (which is only available as postgres extension) any such implementation would bound to be unreliable. I'm not sure that's something the project should be willing to support |
@edholland Thanks for the response! By the way, the example with register_user() ->
pgapp:with_transaction(pool1, fun() ->
users:create_user(),
stats:update_stats()
end).
% module users.erl
create_user() ->
pgapp:with_transaction(pool1, fun() ->
pgapp:squery("insert ..."),
pgapp:squery("update ...")
end).
% module stats.erl
update_stats() ->
pgapp:squery(pool1, "update ..."). So, my app uses different databases so I need a connection pool for each database. This means I must specify a pool I want to use every time I do a query or start a transaction. In the example above all the queries are for register_user() ->
pgapp:with_transaction(pool1, fun() ->
pgapp:squery("insert ..."),
pgapp:squery("update ...")
pgapp:squery(pool1, "update ...").
end). In the current P.S.
We cannot stop the user doing something like this anyway, even in the current |
In your examples you're using
|
@edholland For the same reason it is ok to allow to specify timeout inside the callback. It must be ignored by |
@edholland My example is correct. All queries are using |
I'll have to think about this some, but I do think that, given the small number of users, if we need to change the API to improve the code, it's best to do so. |
Couldn't this issue be simplified by not running the queries in a worker? Instead use the pool only to checkout a connection, use it and return it? This would also help solve #20 . |
The README file contains this example:
The problem in this approach is that "BEGIN" and "COMMIT" actually happens in one connection, but all the queries inside happens in another.
Look at the following code of pgapp_worker.erl:
middle_man_transaction()
will dedicate a separate poolboy worker for each query, including a transaction itself. So whenwith_transaction()
is called, it gets a poolboy worker and runs "BEGIN" in it (inside epsql.erl). Thus the worker is busy waiting for the queries to be executed. But the queries run as separate calls to poolboy which means they get different workers.The text was updated successfully, but these errors were encountered: