I'm not sure if carrying a transaction across multiple requests is possible, 
mainly because you can't be assured of getting the same connection to the 
database across requests.

Looking through the code, it does appear to be possible to override the 
default commit behavior at the end of a successful response. gluon/main.py, 
around line 470:

                if response._custom_commit:
                    response._custom_commit()
                else:
                    BaseAdapter.close_all_instances('commit')

So in your controller you could technically do something like this:

def my_action():
  def no_commit():
    pass
  response._custom_commit = no_commit

  db.table.insert(...)
  return dict(...)

and web2py would execute your empty "no_commit" function rather than the 
normal db commit. However, the db connection will probably get closed anyway 
and the transaction lost unless you have connection pooling enabled. And 
with a pool, the next time a request comes in, it's likely that you will get 
assigned a different connection to the database which does not have the 
transaction state that you left behind. Perhaps even more surprisingly, if 
somebody else gets your old db connection mid-transaction and their action 
does a normal commit, your incomplete data will get written to the database.

This is all guesswork on my part - it's possible web2py has some clever way 
of handling this that I don't know about. But for cases like multi-page 
wizards, it seems preferable to build up your data structure in the session, 
and then insert and commit after the final confirmation page. I'm having 
trouble thinking of a case where data size would prohibit this. Perhaps if 
one or more large file uploads are part of the process -- but in that case 
the file contents are sitting the uploads folder, and you can just store the 
path of the stored file in your session structure. 

If you have an example where this breaks down, it would be interesting to 
consider.

Cheers,
Kevin

Reply via email to