[postmodern-devel] Postgres transaction warnings and save-dao
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi all, I'm using postmodern with great success but I keep seeing these two warnings in my log: - "Postgres warning: there is no transaction in progress" - "Warning while processing connection: Postgres warning: there is already a transaction in progress" As far as I can tell these are merely warnings but they're filling up my logs so I had a look at what was causing it and I found that save-dao has a (with-transaction () ...) wrapping an insert-dao and I was calling save-dao from within my own transaction block. Now if just remove the with-transaction from save-dao an duplicate key violation will ruin the outer transaction by just aborting it (regardless of the error handling code. However if I add a savepoint just before trying insert-dao and in the error handling code use rollback-savepoint to restore to this savepoint I can make the warnings go away. The problem now being that save-dao expects to be called within a with-transaction form. So I was wondering if there is some way to tell if we are within a transaction (e.g. within-transaction-p)? Then I would be able to make a modification that handles both cases. It might then look something like this: (defun save-dao (dao) (if (within-transaction-p) (with-savepoint save-dao (handler-case (progn (insert-dao dao) t) (cl-postgres-error:unique-violation () (rollback-savepoint save-dao) (update-dao dao) nil)))) (handler-case (with-transaction () (insert-dao dao) t) (cl-postgres-error:unique-violation () (update-dao dao) nil))) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkuWEs8ACgkQ0brSZD05ZzAj7wCfbhPynKyGMStzsRP/3MIGpOSH 6IcAni232P2lQ8/hAh5+03NmFr0FSbMs =EIRi -----END PGP SIGNATURE-----
Hello Peter, It seems that transaction was a misguided attempt (apparently I believed postgres supported nested transactions at the time) to prevent the failure to insert from abandoning the transaction. I think the cleanest solution at this point is to add a variant, save-dao/transaction, that uses a savepoint, and declare the regular save-dao to only be safe outside of transactions. I've pushed this change to the repository. Best, Marijn
I've also had the need for determining the state of a transaction. Previously, I'd defined a local WITH-TRANSACTION macro that bound a special variable *TRANSACTION* with the transaction in progress. I have attached a patch that does just that. WITHIN-TRANSACTION-P will return T if a transaction is open. I've not exported *TRANSACTION* because I'm unsure whether this should be part of the public interface. I'm yet to come up with a less hands-on approach to nested transactions, but this allows options for experiments outside of the postmodern proper. For example, my ENSURE-TRANSACTION macro. Really, I should be using savepoints, but this allows me some more flexibility in how I layer my database access methods. I'm not sure if this is appropriate, but if you think it is useful enough, I can prepare a patch to include this as well. (defmacro ensure-transaction ((&optional name) &body body) `(flet ((exec-body () (let ,(if name `((,name postmodern::*transaction*))) ,@body))) (if (within-transaction-p) (exec-body) (with-transaction (,name) (exec-body))))) -- Daniel White
Hey Daniel, I'd say something like this works best as a project-local hack, rather than part of the library interface. The user can perfectly well do (execute "begin") outside of the macro, causing the *transaction* variable to no longer reflect the actual situation. Best, Marijn
On Tue, Mar 9, 2010 at 10:16 PM, Marijn Haverbeke <marijnh@gmail.com> wrote:
I'd say something like this works best as a project-local hack, rather than part of the library interface. The user can perfectly well do (execute "begin") outside of the macro, causing the *transaction* variable to no longer reflect the actual situation.
Maybe with a better docstring explicitly stating that it is limited to only knowing of transactions initiated with the WITH-TRANSACTION macro. -- Daniel White
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Marijn Haverbeke wrote:
Hey Daniel,
I'd say something like this works best as a project-local hack, rather than part of the library interface. The user can perfectly well do (execute "begin") outside of the macro, causing the *transaction* variable to no longer reflect the actual situation.
I agree that the pragmatic solution suggested is not a perfect one but I'm leaning this way myself since I'm using with-transaction very consistently. The best way would of course be if one could interrogate postgresql about its transaction state so that it could catch explicit statements like (execute "begin"). I implemented within-transaction-p using a special variable and a small modification to within-transaction to bind it and with these tools save-dao can be fixed for both when within and outside of a transaction without generating any warnings. For me the problem with the explicit solution of save-dao and save-dao/transaction is that it can't be used to build any transaction agnostic abstractions. Anyhow, this solution is good enough for now (and me). Thanks for all the input! /Peter
Best, Marijn
_______________________________________________ postmodern-devel mailing list postmodern-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/postmodern-devel -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkuWO7UACgkQ0brSZD05ZzDgBACgytukmnKbo8B9h5MfgEAzv4MA np4AnjHYjpTdFHXMg4kKKC6W5mMbeQZ5 =M80q -----END PGP SIGNATURE-----
participants (3)
-
Daniel White
-
Marijn Haverbeke
-
Peter Stiernström