Fixed requests "getIdent" to retorn an unique id even in case of running as a asyncio task

This commit is contained in:
Adolfo Gómez García 2021-10-20 21:52:30 +02:00
parent 27535d4b43
commit 3a9312efe0

View File

@ -29,6 +29,10 @@
""" """
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com .. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
""" """
import asyncio
import contextvars
import random
import datetime
import threading import threading
import datetime import datetime
import weakref import weakref
@ -56,21 +60,35 @@ class ExtendedHttpRequestWithUser(ExtendedHttpRequest):
user: User user: User
identity_context: contextvars.ContextVar[int] = contextvars.ContextVar('identity')
# Return an unique id for the current running thread or the current running coroutine
def getIdent() -> int: def getIdent() -> int:
ident = threading.current_thread().ident # Defect if we are on a thread or on asyncio
return ident if ident else -1 try:
if asyncio.get_event_loop().is_running():
if identity_context.get(None) is None:
identity_context.set(
# Generate a really unique random number for the asyncio task based on current time
# lower 16 are random, upper bits are based on current time
random.randint(0, 2 ** 16 - 1)
+ int(datetime.datetime.now().timestamp()) * 2 ** 16
) # Every "task" has its own context
return identity_context.get()
except Exception:
pass
return threading.current_thread().ident or -1
def getRequest() -> ExtendedHttpRequest: def getRequest() -> ExtendedHttpRequest:
ident = getIdent() ident = getIdent()
if ident in _requests: val = (
val = typing.cast( typing.cast(typing.Optional[ExtendedHttpRequest], _requests[ident][0]())
typing.Optional[ExtendedHttpRequest], _requests[ident][0]() if ident in _requests
) # Return obj from weakref else None
if val: ) # Return obj from weakref
return val
return ExtendedHttpRequest() return val or ExtendedHttpRequest()
def delCurrentRequest() -> None: def delCurrentRequest() -> None:
@ -87,9 +105,9 @@ def delCurrentRequest() -> None:
def cleanOldRequests() -> None: def cleanOldRequests() -> None:
logger.debug('Cleaning stuck requests from %s', _requests) logger.debug('Cleaning stuck requests from %s', _requests)
# No request lives 60 seconds, so 60 seconds is fine # No request lives 3600 seconds, so 3600 seconds is fine
cleanFrom: datetime.datetime = datetime.datetime.now() - datetime.timedelta( cleanFrom: datetime.datetime = datetime.datetime.now() - datetime.timedelta(
seconds=60 seconds=3600
) )
toDelete: typing.List[int] = [] toDelete: typing.List[int] = []
for ident, request in _requests.items(): for ident, request in _requests.items():