async def with_transaction( self, callback: Callable[["AsyncClientSession"], Coroutine[Any, Any, Results]], *, read_concern: Optional[ReadConcern] = None, write_concern: Optional[WriteConcern] = None, read_preference: Optional[ReadPreferences] = None, max_commit_time_ms: Optional[int] = None) -> Results: # 99% Of this code from motor's lib def _within_time_limit(s: float) -> bool: return monotonic_time.time() - s < 120 def _max_time_expired_error(exc: PyMongoError) -> bool: return isinstance(exc, OperationFailure) and exc.code == 50 start_time = monotonic_time.time() while True: async with self.start_transaction( read_concern=read_concern, write_concern=write_concern, read_preference=read_preference, max_commit_time_ms=max_commit_time_ms): try: ret = await callback(self) except Exception as exc: if self.in_transaction: await self.abort_transaction() if (isinstance(exc, PyMongoError) and exc.has_error_label("TransientTransactionError") and _within_time_limit(start_time)): # Retry the entire transaction. continue raise if not self.in_transaction: # Assume callback intentionally ended the transaction. return ret while True: try: await self.commit_transaction() except PyMongoError as exc: if (exc.has_error_label("UnknownTransactionCommitResult") and _within_time_limit(start_time) and not _max_time_expired_error(exc)): # Retry the commit. continue if (exc.has_error_label("TransientTransactionError") and _within_time_limit(start_time)): # Retry the entire transaction. break raise # Commit succeeded. return ret
def sleep(seconds): loop = IOLoop.current() loop.add_timeout(time.time() + seconds, loop.stop) loop.start()
def _within_time_limit(s: float) -> bool: return monotonic_time.time() - s < 120