Forsøkt å fikse hengeproblemet.

Jeg tror grunnen til at programmet henger iblant er at det finnes
flere åpne sesjoner, og at en annen sesjon har låst noe den aktive
sesjonen vil bruke.

De fleste menyene som ikke gjorde noen endringer lukket ikke sesjonen
sin, og selv de som gjorde endringer lukket sesjonen bare hvis de ble
fullført, ikke hvis de ble avbrutt.

Jeg har flyttet all åpning og lukking av sesjoner til funksjonen
Menu.execute, og lagt til egenskapen Menu.uses_db.  For menyer som har
denne egenskapen satt til True lages det en sesjon i begynnelsen av
execute, og den lukkes før execute returnerer (lukkingen er beskyttet
av en finally).

Tips for debugging av denne typen problemer (dersom de vedvarer):

SELECT * FROM pg_stat_activity;
SELECT * FROM pg_locks;
This commit is contained in:
Øystein Ingmar Skartsæterhagen 2010-05-16 18:43:41 +00:00
parent 945e6529f5
commit a0ac2bd633
1 changed files with 21 additions and 31 deletions

View File

@ -22,7 +22,7 @@ class Menu():
def __init__(self, name, items=[], prompt='> ', def __init__(self, name, items=[], prompt='> ',
return_index=True, return_index=True,
exit_msg=None, exit_confirm_msg=None, exit_disallowed_msg=None, exit_msg=None, exit_confirm_msg=None, exit_disallowed_msg=None,
help_text=None): help_text=None, uses_db=False):
self.name = name self.name = name
self.items = items self.items = items
self.prompt = prompt self.prompt = prompt
@ -33,6 +33,7 @@ class Menu():
self.help_text = help_text self.help_text = help_text
self.context = None self.context = None
self.header_format = '[%s]' self.header_format = '[%s]'
self.uses_db = uses_db
def exit_menu(self): def exit_menu(self):
if self.exit_disallowed_msg != None: if self.exit_disallowed_msg != None:
@ -321,10 +322,18 @@ product name or barcode.
def execute(self): def execute(self):
self.set_context(None) self.set_context(None)
try: try:
if self.uses_db:
self.session = Session()
else:
self.session = None
return self._execute() return self._execute()
except ExitMenu: except ExitMenu:
self.at_exit() self.at_exit()
return None return None
finally:
if self.session != None:
self.session.close()
self.session = None
def _execute(self): def _execute(self):
while True: while True:
@ -404,11 +413,11 @@ class ConfirmMenu(Menu):
class TransferMenu(Menu): class TransferMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Transfer credit between users') Menu.__init__(self, 'Transfer credit between users',
uses_db=True)
def _execute(self): def _execute(self):
self.print_header() self.print_header()
self.session = Session()
amount = self.input_int('Transfer amount> ', (1,100000)) amount = self.input_int('Transfer amount> ', (1,100000))
self.set_context('Transfering %d kr' % amount, display=False) self.set_context('Transfering %d kr' % amount, display=False)
user1 = self.input_user('From user> ') user1 = self.input_user('From user> ')
@ -431,17 +440,15 @@ class TransferMenu(Menu):
print 'User %s\'s credit is now %d kr' % (user2, user2.credit) print 'User %s\'s credit is now %d kr' % (user2, user2.credit)
except sqlalchemy.exc.SQLAlchemyError, e: except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not perform transfer: %s' % e print 'Could not perform transfer: %s' % e
self.session.close()
self.pause() self.pause()
class AddUserMenu(Menu): class AddUserMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Add user') Menu.__init__(self, 'Add user', uses_db=True)
def _execute(self): def _execute(self):
self.print_header() self.print_header()
self.session = Session()
username = self.input_str('Username (should be same as PVV username)> ', User.name_re, (1,10)) username = self.input_str('Username (should be same as PVV username)> ', User.name_re, (1,10))
cardnum = self.input_str('Card number (optional)> ', User.card_re, (0,10)) cardnum = self.input_str('Card number (optional)> ', User.card_re, (0,10))
user = User(username, cardnum) user = User(username, cardnum)
@ -451,13 +458,12 @@ class AddUserMenu(Menu):
print 'User %s stored' % username print 'User %s stored' % username
except sqlalchemy.exc.IntegrityError, e: except sqlalchemy.exc.IntegrityError, e:
print 'Could not store user %s: %s' % (username,e) print 'Could not store user %s: %s' % (username,e)
self.session.close()
self.pause() self.pause()
class EditUserMenu(Menu): class EditUserMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Edit user') Menu.__init__(self, 'Edit user', uses_db=True)
self.help_text = ''' self.help_text = '''
The only editable part of a user is its card number. The only editable part of a user is its card number.
@ -467,7 +473,6 @@ user (write an empty line to remove the card number).
def _execute(self): def _execute(self):
self.print_header() self.print_header()
self.session = Session()
user = self.input_user('User> ') user = self.input_user('User> ')
self.printc('Editing user %s' % user.name) self.printc('Editing user %s' % user.name)
card_str = '"%s"' % user.card card_str = '"%s"' % user.card
@ -481,16 +486,14 @@ user (write an empty line to remove the card number).
print 'User %s stored' % user.name print 'User %s stored' % user.name
except sqlalchemy.exc.SQLAlchemyError, e: except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store user %s: %s' % (user.name,e) print 'Could not store user %s: %s' % (user.name,e)
self.session.close()
self.pause() self.pause()
class AddProductMenu(Menu): class AddProductMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Add product') Menu.__init__(self, 'Add product', uses_db=True)
def _execute(self): def _execute(self):
self.session = Session()
self.print_header() self.print_header()
bar_code = self.input_str('Bar code> ', Product.bar_code_re, (8,13)) bar_code = self.input_str('Bar code> ', Product.bar_code_re, (8,13))
name = self.input_str('Name> ', Product.name_re, (1,30)) name = self.input_str('Name> ', Product.name_re, (1,30))
@ -502,17 +505,15 @@ class AddProductMenu(Menu):
print 'Product %s stored' % name print 'Product %s stored' % name
except sqlalchemy.exc.SQLAlchemyError, e: except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store product %s: %s' % (name,e) print 'Could not store product %s: %s' % (name,e)
self.session.close()
self.pause() self.pause()
class EditProductMenu(Menu): class EditProductMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Edit product') Menu.__init__(self, 'Edit product', uses_db=True)
def _execute(self): def _execute(self):
self.print_header() self.print_header()
self.session = Session()
product = self.input_product('Product> ') product = self.input_product('Product> ')
self.printc('Editing product %s' % product.name) self.printc('Editing product %s' % product.name)
while True: while True:
@ -531,7 +532,6 @@ class EditProductMenu(Menu):
print 'Product %s stored' % product.name print 'Product %s stored' % product.name
except sqlalchemy.exc.SQLAlchemyError, e: except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store product %s: %s' % (product.name, e) print 'Could not store product %s: %s' % (product.name, e)
self.session.close()
self.pause() self.pause()
return return
elif what == None: elif what == None:
@ -543,10 +543,9 @@ class EditProductMenu(Menu):
class ShowUserMenu(Menu): class ShowUserMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Show user') Menu.__init__(self, 'Show user', uses_db=True)
def _execute(self): def _execute(self):
self.session = Session()
self.print_header() self.print_header()
user = self.input_user('User name or card number> ') user = self.input_user('User name or card number> ')
print 'User name: %s' % user.name print 'User name: %s' % user.name
@ -582,11 +581,10 @@ class ShowUserMenu(Menu):
class UserListMenu(Menu): class UserListMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'User list') Menu.__init__(self, 'User list', uses_db=True)
def _execute(self): def _execute(self):
self.print_header() self.print_header()
self.session = Session()
user_list = self.session.query(User).all() user_list = self.session.query(User).all()
total_credit = self.session.query(sqlalchemy.func.sum(User.credit)).first()[0] total_credit = self.session.query(sqlalchemy.func.sum(User.credit)).first()[0]
@ -598,14 +596,12 @@ class UserListMenu(Menu):
print line_format % (user.name, user.credit) print line_format % (user.name, user.credit)
print hline print hline
print line_format % ('total credit', total_credit) print line_format % ('total credit', total_credit)
self.session.close()
self.pause() self.pause()
class BuyMenu(Menu): class BuyMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Buy') Menu.__init__(self, 'Buy', uses_db=True)
self.help_text = ''' self.help_text = '''
Each purchase may contain one or more products and one or more buyers. Each purchase may contain one or more products and one or more buyers.
@ -618,7 +614,6 @@ When finished, write an empty line to confirm the purchase.
def _execute(self): def _execute(self):
self.print_header() self.print_header()
self.session = Session()
self.purchase = Purchase() self.purchase = Purchase()
self.exit_confirm_msg=None self.exit_confirm_msg=None
while True: while True:
@ -659,7 +654,6 @@ When finished, write an empty line to confirm the purchase.
self.print_purchase() self.print_purchase()
for t in self.purchase.transactions: for t in self.purchase.transactions:
print 'User %s\'s credit is now %d kr' % (t.user.name, t.user.credit) print 'User %s\'s credit is now %d kr' % (t.user.name, t.user.credit)
self.session.close()
self.pause() self.pause()
return True return True
@ -698,11 +692,10 @@ When finished, write an empty line to confirm the purchase.
class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combined to one class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combined to one
def __init__(self): def __init__(self):
Menu.__init__(self, 'Adjust credit') Menu.__init__(self, 'Adjust credit', uses_db=True)
def _execute(self): def _execute(self):
self.print_header() self.print_header()
self.session = Session()
user = self.input_user('User> ') user = self.input_user('User> ')
print 'User %s\'s credit is %d kr' % (user.name, user.credit) print 'User %s\'s credit is %d kr' % (user.name, user.credit)
self.set_context('Adjusting credit for user %s' % user.name, display=False) self.set_context('Adjusting credit for user %s' % user.name, display=False)
@ -718,24 +711,21 @@ class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combine
print 'User %s\'s credit is now %d kr' % (user.name, user.credit) print 'User %s\'s credit is now %d kr' % (user.name, user.credit)
except sqlalchemy.exc.SQLAlchemyError, e: except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store transaction: %s' % e print 'Could not store transaction: %s' % e
self.session.close()
self.pause() self.pause()
class ProductListMenu(Menu): class ProductListMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Product list') Menu.__init__(self, 'Product list', uses_db=True)
def _execute(self): def _execute(self):
self.print_header() self.print_header()
self.session = Session()
product_list = self.session.query(Product).all() product_list = self.session.query(Product).all()
line_format = '%-30s | %6s | %-15s' line_format = '%-30s | %6s | %-15s'
print line_format % ('name', 'price', 'bar code') print line_format % ('name', 'price', 'bar code')
print '---------------------------------------------------------' print '---------------------------------------------------------'
for p in product_list: for p in product_list:
print line_format % (p.name, p.price, p.bar_code) print line_format % (p.name, p.price, p.bar_code)
self.session.close()
self.pause() self.pause()