2016-09-15 6 views
0

私のCherryPy + Peeweeアプリケーションでは、トランザクションを開始し、操作のリストを実行し、結果を示すページを返します。いずれかの操作で問題が発生した場合は、ロギングテーブルに行を追加し、その行を示すページにリダイレクトします。失敗したトランザクションでSQLコードを実行する

CherryPyのリダイレクトは例外を発生させることによって実行され、例外によっていくつかのトランザクションがロールバックされるという問題があります。ロールバックは、失敗した操作(およびそれが成功したとしても以前のすべての操作)に必要なものですが、ログに必要なものではありません。次のコードでたとえば

は、ユーザーがa_page?a=1&b=2&c=3に行く場合:

  • do_thisx != yを見つけ、show_message
  • do_thisTable1
  • do_thatx == yを見つけて実行します上の一つのレコードを更新します実行されませんshow_message
  • show_messageは、1行Table1上の取引では、更新の両方がで作られている間に例外が上がってきたので、順番に例外が発生します
  • show_message電子Messageログテーブルは、ちょうど

をログに記録されたメッセージが表示されますそのページにリダイレクトしますdo_thisとなり、show_messageにログインしたメッセージはロールバックされます。

ロギングテーブルの行をコミットし、その他の変更をすべてロールバックする方法はありますか。それは(ないことを確認まだ)ネストされたトランザクションでは動作しない場合がありますので、

@cherrypy.expose 
def a_page(self, a, b, c): 
    with db.transaction(): 
     self.do_this(a, b) 
     self.do_that(b, c) 
    return render('it_worked.html') 

def do_this(self, x, y): 
    if x == y: 
     self.show_message('Wrong this') 
    Table1.update(f2=x).where(f1 == y).execute() 

def do_that(self, x, y): 
    if x != y: 
     self.show_message('Wrong that') 
    Table1.update(f3=x).where(f1 == z).execute() 

def show_message(self, message) 
    msg = Message.create(msg=message) 
    raise cherrypy.HTTPRedirect('show_message?id={}'.format(msg.id)) 
+0

おそらくネストされたトランザクション、つまりセーブポイント。 –

+0

@ CL。私が知っている限り、入れ子にされたトランザクションは内部操作を保存しないことを可能にします。私は反対が必要です:私は今まで実行されたトランザクションを保存したくないですが、私は最後のトランザクションを保存したいと思います。 – stenci

+0

私は、(1)トランザクションを関数に渡す必要があり、(2)入れ子になっているトランザクションがあるとうまくいかないために、好きではない解決策を見つけました。それは私の答えです。それが良い解決策であるか、私がよりうまくいくかどうか教えてください。 – stenci

答えて

0

このソリューションは、動作しているようですが、それは関数にトランザクションをダウン渡す必要があるため、私は好きではない、と。

import cherrypy 
import peewee 

db = peewee.SqliteDatabase('test.db', threadlocals=True) 

class PeeweeModel(peewee.Model): 
    class Meta: 
     database = db 

class Table1(PeeweeModel): 
    field1 = peewee.CharField() 

Table1.drop_table(True) 
Table1.create_table(True) 

class Log(PeeweeModel): 
    msg = peewee.CharField() 

    @staticmethod 
    def show_log(msg, txn): 
     txn.rollback() 
     msg = Log.create(msg=msg) 
     txn.commit() 
     raise cherrypy.HTTPRedirect('show_log?msg_id={}'.format(msg.id)) 

Log.drop_table(True) 
Log.create_table(True) 

def table_content(): 
    return '<br>'.join(['{} {}'.format(row.id, row.field1) for row in Table1.select()]) 

html = """<!DOCTYPE HTML> 
<html> 
<head> 
</head> 
<body> 
<a href="index">index</a><br> 
<a href="add_row">add_row</a><br> 
{}<br> 
Table1<br> 
{}<br> 
</body> 
</html>""" 

class App(): 

    @cherrypy.expose 
    def index(self, msg='Hello'): 
     return html.format(msg, table_content()) 

    @cherrypy.expose 
    def add_row(self): 
     with db.transaction() as txn: 
      Table1.update(field1=Table1.field1 + 1).execute() 
      Table1.update(field1=Table1.field1 + 1).where(Table1.id == 2).execute() 
      if Table1.select().count() == 5: 
       raise Log.show_log('Something went wrong', txn) 
      Table1.create(field1=1, field2=2) 
     return html.format('Added record to Table1', table_content()) 

    @cherrypy.expose 
    def show_log(self, msg_id): 
     msg = Log.get(Log.id == msg_id) 
     text = 'Message id {}: {}'.format(msg.id, msg.msg) 
     return html.format(text, table_content()) 

cherrypy.quickstart(App(), '/') 
関連する問題