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

View File

@ -22,7 +22,7 @@ class Menu():
def __init__(self, name, items=[], prompt='> ',
return_index=True,
exit_msg=None, exit_confirm_msg=None, exit_disallowed_msg=None,
help_text=None):
help_text=None, uses_db=False):
self.name = name
self.items = items
self.prompt = prompt
@ -33,6 +33,7 @@ class Menu():
self.help_text = help_text
self.context = None
self.header_format = '[%s]'
self.uses_db = uses_db
def exit_menu(self):
if self.exit_disallowed_msg != None:
@ -321,10 +322,18 @@ product name or barcode.
def execute(self):
self.set_context(None)
try:
if self.uses_db:
self.session = Session()
else:
self.session = None
return self._execute()
except ExitMenu:
self.at_exit()
return None
finally:
if self.session != None:
self.session.close()
self.session = None
def _execute(self):
while True:
@ -404,11 +413,11 @@ class ConfirmMenu(Menu):
class TransferMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Transfer credit between users')
Menu.__init__(self, 'Transfer credit between users',
uses_db=True)
def _execute(self):
self.print_header()
self.session = Session()
amount = self.input_int('Transfer amount> ', (1,100000))
self.set_context('Transfering %d kr' % amount, display=False)
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)
except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not perform transfer: %s' % e
self.session.close()
self.pause()
class AddUserMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Add user')
Menu.__init__(self, 'Add user', uses_db=True)
def _execute(self):
self.print_header()
self.session = Session()
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))
user = User(username, cardnum)
@ -451,13 +458,12 @@ class AddUserMenu(Menu):
print 'User %s stored' % username
except sqlalchemy.exc.IntegrityError, e:
print 'Could not store user %s: %s' % (username,e)
self.session.close()
self.pause()
class EditUserMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Edit user')
Menu.__init__(self, 'Edit user', uses_db=True)
self.help_text = '''
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):
self.print_header()
self.session = Session()
user = self.input_user('User> ')
self.printc('Editing user %s' % user.name)
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
except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store user %s: %s' % (user.name,e)
self.session.close()
self.pause()
class AddProductMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Add product')
Menu.__init__(self, 'Add product', uses_db=True)
def _execute(self):
self.session = Session()
self.print_header()
bar_code = self.input_str('Bar code> ', Product.bar_code_re, (8,13))
name = self.input_str('Name> ', Product.name_re, (1,30))
@ -502,17 +505,15 @@ class AddProductMenu(Menu):
print 'Product %s stored' % name
except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store product %s: %s' % (name,e)
self.session.close()
self.pause()
class EditProductMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Edit product')
Menu.__init__(self, 'Edit product', uses_db=True)
def _execute(self):
self.print_header()
self.session = Session()
product = self.input_product('Product> ')
self.printc('Editing product %s' % product.name)
while True:
@ -531,7 +532,6 @@ class EditProductMenu(Menu):
print 'Product %s stored' % product.name
except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store product %s: %s' % (product.name, e)
self.session.close()
self.pause()
return
elif what == None:
@ -543,10 +543,9 @@ class EditProductMenu(Menu):
class ShowUserMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Show user')
Menu.__init__(self, 'Show user', uses_db=True)
def _execute(self):
self.session = Session()
self.print_header()
user = self.input_user('User name or card number> ')
print 'User name: %s' % user.name
@ -582,11 +581,10 @@ class ShowUserMenu(Menu):
class UserListMenu(Menu):
def __init__(self):
Menu.__init__(self, 'User list')
Menu.__init__(self, 'User list', uses_db=True)
def _execute(self):
self.print_header()
self.session = Session()
user_list = self.session.query(User).all()
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 hline
print line_format % ('total credit', total_credit)
self.session.close()
self.pause()
class BuyMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Buy')
Menu.__init__(self, 'Buy', uses_db=True)
self.help_text = '''
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):
self.print_header()
self.session = Session()
self.purchase = Purchase()
self.exit_confirm_msg=None
while True:
@ -659,7 +654,6 @@ When finished, write an empty line to confirm the purchase.
self.print_purchase()
for t in self.purchase.transactions:
print 'User %s\'s credit is now %d kr' % (t.user.name, t.user.credit)
self.session.close()
self.pause()
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
def __init__(self):
Menu.__init__(self, 'Adjust credit')
Menu.__init__(self, 'Adjust credit', uses_db=True)
def _execute(self):
self.print_header()
self.session = Session()
user = self.input_user('User> ')
print 'User %s\'s credit is %d kr' % (user.name, user.credit)
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)
except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store transaction: %s' % e
self.session.close()
self.pause()
class ProductListMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Product list')
Menu.__init__(self, 'Product list', uses_db=True)
def _execute(self):
self.print_header()
self.session = Session()
product_list = self.session.query(Product).all()
line_format = '%-30s | %6s | %-15s'
print line_format % ('name', 'price', 'bar code')
print '---------------------------------------------------------'
for p in product_list:
print line_format % (p.name, p.price, p.bar_code)
self.session.close()
self.pause()