Clear the request ID on request_finished, rather than on the way "out" of the middleware#81
Conversation
…d rather than on the way "out" of the middleware
dabapps-robot
left a comment
There was a problem hiding this comment.
Looks good overall — the change makes sense, and moving the cleanup to request_finished feels like a good way to preserve the request ID for the full response lifecycle without leaving it around indefinitely. The test also captures the intended behaviour nicely.
One small thing I’d consider: giving the signal receiver a dispatch_uid. Because this receiver is connected at import time, a dispatch_uid helps protect against duplicate registrations in environments where modules may be imported more than once (eg autoreload / some test setups).
Something along these lines:
@receiver(request_finished, dispatch_uid="log_request_id_clear_request_id")
def _clear_request_id(**kwargs):
...Other than that, this looks ready to merge to me.
|
@dabapps-robot I think that's an edge case, and the receiver is so lightweight that it doesn't really matter if it's called multiple times. |
|
@RealOrangeOne do you want to have a look at this as you authored #75? 🙂 |
#75 refactored
RequestIDMiddlewareand changed whenlocal.request_idis cleared. Before that change, cleanup only happened on theLOG_REQUESTS=Truepath, so with the defaultLOG_REQUESTS=Falsethe request ID remained available after the middleware returned. That behaviour was not documented and appears to have been an unintended side effect of where the cleanup lived, since request-ID lifetime should not depend on whether request logging is enabled. It wasn't quite a bug, but it was certainly a bit odd. After #75 therequest_idwas cleared unconditionally.However, issue #80 showed that some users relied on that "bug", as they are reading
log_request_id.local.request_idfrom outer WSGI wrapper code afterdjango_application(...)returned (in that case, to copy it into a uWSGI log variable).This change moves cleanup to Django’s
request_finishedsignal. That keeps the request ID available for the rest of the request/response lifecycle, including outer WSGI wrapper code that runs immediately after the Django application returns, while still ensuring the value is cleared at the end of the request instead of leaking indefinitely.