nephila / django-meta

Pluggable app to allow Django developers to quickly add meta tags and OpenGraph, Twitter, and Google Plus properties to their HTML responses.
https://django-meta.readthedocs.io
Other
480 stars 68 forks source link

AttributeError _request #115

Closed pySilver closed 3 years ago

pySilver commented 4 years ago

For some reason this error happens from time to time. Django 3.x project is running as ASGI

AttributeError: _request
  File "django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "wagtail/core/views.py", line 24, in serve
    return page.serve(request, *args, **kwargs)
  File "mybaze/core/mixins.py", line 258, in serve
    return view(request, *args, **kwargs)
  File "django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "mybaze/catalog/views.py", line 1062, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "django/views/generic/base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File "mybaze/catalog/views.py", line 1106, in get
    meta=self.get_meta(),
  File "mybaze/catalog/views.py", line 957, in get_meta
    meta = self.parent_page.as_meta(request=self.request)
  File "meta/models.py", line 102, in as_meta
    for field, data in self._retrieve_data(request, metadata):
  File "meta/models.py", line 72, in _retrieve_data
    yield field, data
  File "contextlib.py", line 120, in __exit__
    next(self.gen)
  File "meta/models.py", line 121, in _set_request
    delattr(self, '_request')
yakky commented 4 years ago

@pySilver thanks for reporting. I have not tested this package in an ASGI environment. Does this happens on Django 3.0 or are you testing on 3.1? Which is the python version are you running on?

pySilver commented 4 years ago

@yakky its django 3.0.x running on python 3.8.x ;

Deployed as described here in Gunicorn section: https://www.uvicorn.org/deployment/

Sadly, the issue is not happening constantly since it's staging environment with a low traffic at the moment. But the issue pops up often in sentry :/

Looks like multiple requests shares the same model instance so race condition appears when it comes to delattr. Im not an expert in async (yet..). Maybe the only workaround would be passing request object to every handler, instead of making it available in temporary attribute.

yakky commented 4 years ago

Alternatively it should be possible to thread locals, which has an ASGI safe implementation

pySilver commented 4 years ago

You mean using Local from asgiref.local ? Django 3.0.x uses this for language activation and such things. However i think it would look rly strange here.

yakky commented 3 years ago

@pySilver I have been unable to reproduce the error, but using thread locals should fix it anyway

You can test the linked PR if it fixes your error

pySilver commented 3 years ago

I've had this issue all the time. However I fixed it by moving request away from model.

yakky commented 3 years ago

@pySilver I trust that, but I couldn't fine a way to reproduce it in tests

The implemented solutions is basically to remove the request from the model object as you did

pySilver commented 3 years ago

Yeah, I couldn't reproduce it with test either. It happens on race condition only when one request sets request object while other removes. It might be also related to pickling model instances to cache layer.

yakky commented 3 years ago

@pySilver I agree with your analysis, and in hindsight caching request on the model has been a bad decision :)