Mercurial > p > roundup > code
comparison roundup/backends/sessions_dbm.py @ 6823:fe0091279f50
Refactor session db logging and key generation for sessions/otks
While I was working on the redis sessiondb stuff, I noticed that
log_wanrning, get_logger ... was duplicated. Also there was code to
generate a unique key for otks that was duplicated.
Changes:
creating new sessions_common.py and SessionsCommon class to provide
methods:
log_warning, log_info, log_debug, get_logger, getUniqueKey
getUniqueKey method is closer to the method used to make
session keys in client.py.
sessions_common.py now report when random_.py chooses a weak
random number generator. Removed same from rest.py.
get_logger reconciles all logging under
roundup.hyperdb.backends.<name of BasicDatabase class>
some backends used to log to root logger.
have BasicDatabase in other sessions_*.py modules inherit from
SessionCommon.
change logging to use log_* methods.
In addition:
remove unused imports reported by flake8 and other formatting
changes
modify actions.py, rest.py, templating.py to use getUniqueKey
method.
add tests for new methods
test_redis_session.py
swap out ModuleNotFoundError for ImportError to prevent crash in
python2 when redis is not present.
allow injection of username:password or just password into redis
connection URL. set pytest_redis_pw envirnment variable to password
or user:password when running test.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sun, 07 Aug 2022 01:51:11 -0400 |
| parents | 375d40a9e730 |
| children | 39c482e6a246 |
comparison
equal
deleted
inserted
replaced
| 6822:5053ee6c846b | 6823:fe0091279f50 |
|---|---|
| 4 Yes, it's called "sessions" - because originally it only defined a session | 4 Yes, it's called "sessions" - because originally it only defined a session |
| 5 class. It's now also used for One Time Key handling too. | 5 class. It's now also used for One Time Key handling too. |
| 6 """ | 6 """ |
| 7 __docformat__ = 'restructuredtext' | 7 __docformat__ = 'restructuredtext' |
| 8 | 8 |
| 9 import os, marshal, time, logging, random | 9 import marshal, os, random, time |
| 10 | 10 |
| 11 from roundup.anypy.html import html_escape as escape | 11 from roundup.anypy.html import html_escape as escape |
| 12 | 12 |
| 13 from roundup import hyperdb | 13 from roundup import hyperdb |
| 14 from roundup.i18n import _ | 14 from roundup.i18n import _ |
| 15 from roundup.anypy.dbm_ import anydbm, whichdb | 15 from roundup.anypy.dbm_ import anydbm, whichdb |
| 16 | 16 from roundup.backends.sessions_common import SessionCommon |
| 17 | 17 |
| 18 class BasicDatabase: | 18 |
| 19 class BasicDatabase(SessionCommon): | |
| 19 ''' Provide a nice encapsulation of an anydbm store. | 20 ''' Provide a nice encapsulation of an anydbm store. |
| 20 | 21 |
| 21 Keys are id strings, values are automatically marshalled data. | 22 Keys are id strings, values are automatically marshalled data. |
| 22 ''' | 23 ''' |
| 23 _db_type = None | 24 _db_type = None |
| 86 finally: | 87 finally: |
| 87 db.close() | 88 db.close() |
| 88 | 89 |
| 89 def set(self, infoid, **newvalues): | 90 def set(self, infoid, **newvalues): |
| 90 db = self.opendb('c') | 91 db = self.opendb('c') |
| 91 timestamp=None | 92 timestamp = None |
| 92 try: | 93 try: |
| 93 if infoid in db: | 94 if infoid in db: |
| 94 values = marshal.loads(db[infoid]) | 95 values = marshal.loads(db[infoid]) |
| 95 try: | 96 try: |
| 96 timestamp = values['__timestamp'] | 97 timestamp = values['__timestamp'] |
| 145 | 146 |
| 146 # open the database with the correct module | 147 # open the database with the correct module |
| 147 dbm = __import__(db_type) | 148 dbm = __import__(db_type) |
| 148 | 149 |
| 149 retries_left = 15 | 150 retries_left = 15 |
| 150 logger = logging.getLogger('roundup.hyperdb.backend.sessions') | |
| 151 while True: | 151 while True: |
| 152 try: | 152 try: |
| 153 handle = dbm.open(path, mode) | 153 handle = dbm.open(path, mode) |
| 154 break | 154 break |
| 155 except OSError as e: | 155 except OSError as e: |
| 156 # Primarily we want to catch and retry: | 156 # Primarily we want to catch and retry: |
| 157 # [Errno 11] Resource temporarily unavailable retry | 157 # [Errno 11] Resource temporarily unavailable retry |
| 158 # FIXME: make this more specific | 158 # FIXME: make this more specific |
| 159 if retries_left < 10: | 159 if retries_left < 10: |
| 160 logger.warning('dbm.open failed on ...%s, retry %s left: %s, %s'%(path[-15:],15-retries_left,retries_left,e)) | 160 self.log_warning( |
| 161 'dbm.open failed on ...%s, retry %s left: %s, %s' % | |
| 162 (path[-15:], 15-retries_left, retries_left, e)) | |
| 161 if retries_left < 0: | 163 if retries_left < 0: |
| 162 # We have used up the retries. Reraise the exception | 164 # We have used up the retries. Reraise the exception |
| 163 # that got us here. | 165 # that got us here. |
| 164 raise | 166 raise |
| 165 else: | 167 else: |
| 166 # stagger retry to try to get around thundering herd issue. | 168 # stagger retry to try to get around thundering herd issue. |
| 167 time.sleep(random.randint(0,25)*.005) | 169 time.sleep(random.randint(0, 25)*.005) |
| 168 retries_left = retries_left - 1 | 170 retries_left = retries_left - 1 |
| 169 continue # the while loop | 171 continue # the while loop |
| 170 return handle | 172 return handle |
| 171 | 173 |
| 172 def commit(self): | 174 def commit(self): |
