def claim_code(cls, user, deal): # check if they already have a code for this deal and return it try: result = (Session.query(cls).filter( and_(cls.user == user._id, cls.deal == deal)).one()) return result.code except NoResultFound: pass # select an unclaimed code, assign it to the user, and return it try: claiming = (Session.query(cls).filter( and_(cls.deal == deal, cls.user == None, func.pg_try_advisory_lock(cls.id))).limit(1).one()) except NoResultFound: raise GoldPartnerCodesExhaustedError claiming.user = user._id claiming.date = datetime.now(g.tz) Session.add(claiming) Session.commit() # release the lock Session.query(func.pg_advisory_unlock_all()).all() return claiming.code
def claim_code(cls, user, deal): # check if they already have a code for this deal and return it try: result = (Session.query(cls) .filter(and_(cls.user == user._id, cls.deal == deal)) .one()) return result.code except NoResultFound: pass # select an unclaimed code, assign it to the user, and return it try: claiming = (Session.query(cls) .filter(and_(cls.deal == deal, cls.user == None, func.pg_try_advisory_lock(cls.id))) .limit(1) .one()) except NoResultFound: raise GoldPartnerCodesExhaustedError claiming.user = user._id claiming.date = datetime.now(g.tz) Session.add(claiming) Session.commit() # release the lock Session.query(func.pg_advisory_unlock_all()).all() return claiming.code
def grab_lock(self) -> Generator[Tuple[bool, scoped_session], None, None]: """ Yields a boolean value and a new SQLAlchemy session object. The process calling this method should only execute transactions via the session object if the boolean returned is True -- Grab lock * SELECT pg_try_advisory_lock(23); -- Release lock ** SELECT pg_advisory_unlock(23); -- List all advisory locks (all sessions) SELECT mode, classid, objid FROM pg_locks WHERE locktype = 'advisory'; ############################# # EXAMPLE USAGE # ############################# with AdvisoryLock(engine=db.engine, lock_key="6bd4cf27-d68a-4d8a-809c-b07815937052").grab_lock() as locked_session: lock, session = locked_session if lock: # Do stuff with session user = session.query(User).filter_by(id=100).first() user.hint = "someotherhint" session.add(user) """ session = self.session() try: advisory_lock_key = int( hashlib.sha1(self.lock_key.encode("utf-8")).hexdigest(), 16) % (10**8) # * advisory_lock = session.execute( select([func.pg_try_advisory_lock(advisory_lock_key) ])).fetchone()[0] yield (advisory_lock, session) # ** session.execute( select([func.pg_advisory_unlock(advisory_lock_key)])) except: session.rollback() raise finally: session.commit() session.close()
def run(self): # Only let one worker run via pg advisory lock acquired = Session.execute(select([func.pg_try_advisory_lock(importlockid)])).fetchone()[0] threadid = 'PID ' + str(os.getpid()) + ' thread ' + str(threading.current_thread()) if acquired: log.info('[shop worker] %s acquired lock, starting..' % threadid) else: return pendingdownloads = False while True: try: downloads = Session.query(ShopDownload) \ .filter(ShopDownload.isdone==False) \ .filter(ShopDownload.failedimport==False) \ .all() pendingdownloads = len(downloads) != 0 if pendingdownloads: rtorrent = xmlrpclib.ServerProxy(Config.SHOP_RPC_URL) for download in downloads: try: infohash = download.infohash iscomplete = rtorrent.d.get_complete(infohash) == 1 if iscomplete: shopservice.importDownload(download) except: exc_type, exc_value, exc_traceback = sys.exc_info() importtrace = repr(traceback.format_exception(exc_type, exc_value, exc_traceback)) log.error('[shop worker] caught exception in loop ' + importtrace) Session.rollback() Session.begin() download.failedimport = True download.importtrace = importtrace Session.commit() except Exception as e: log.error('[shop worker] caught exception out of loop ' + repr(e)) Session.rollback() if pendingdownloads: time.sleep(10) else: time.sleep(30)