Expected behaviour
Concurrent requests to the same HttpResolver / HttpResolverLocal ASGI application should retain their own bodies, headers, and routing context. Invalid or cancelled requests should not clear another in-flight request's context.
Current behaviour
With native Pydantic validation enabled, six concurrent requests with distinct bodies all return the last request's body. This reproduces with 3.34.0 and current develop. An overlapping validation failure or cancellation can also clear a pending handler's context.
Reproduction
Install aws-lambda-powertools==3.34.0, pydantic, and httpx, then run:
import asyncio
import httpx
from pydantic import BaseModel
from aws_lambda_powertools.event_handler import HttpResolver
class Body(BaseModel):
name: str
app = HttpResolver(enable_validation=True)
@app.post('/echo')
async def echo(body: Body) -> dict:
await asyncio.sleep(0)
return {'name': body.name}
async def main():
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url='http://test') as client:
responses = await asyncio.gather(*(
client.post('/echo', json={'name': str(i)}) for i in range(6)
))
names = [response.json()['name'] for response in responses]
print(names)
assert names == [str(i) for i in range(6)]
asyncio.run(main())
Expected: ['0', '1', '2', '3', '4', '5']
Observed: ['5', '5', '5', '5', '5', '5'], followed by the assertion failure.
Cause and proposed fix
HttpResolverLocal.asgi_handler() assigns BaseRouter.current_event and BaseRouter.lambda_context, then awaits resolution. Routing and validation also mutate a shared self.context dictionary. Validation middleware runs through a thread bridge, allowing another ASGI request to overwrite this state before the first consumes it. Request cleanup can clear another request's context.
A request-scoped state object carried by ContextVar can isolate local ASGI resolution, including middleware threads, without serializing all local requests. I am preparing a focused PR with regressions for distinct bodies, overlapping validation failures, and cancellation.
Scope
This concerns overlapping requests to the local ASGI server, not concurrent invocations within a Lambda execution environment. I understand the Lambda execution model; local ASGI servers nevertheless accept concurrent HTTP requests. This is separate from #8187 / #8196 (the validation-exception deadlock fixed in 3.29.0).
Environment
Python 3.13; Powertools 3.34.0 and current develop; local ASGI, no AWS resources required.
Expected behaviour
Concurrent requests to the same
HttpResolver/HttpResolverLocalASGI application should retain their own bodies, headers, and routing context. Invalid or cancelled requests should not clear another in-flight request's context.Current behaviour
With native Pydantic validation enabled, six concurrent requests with distinct bodies all return the last request's body. This reproduces with 3.34.0 and current
develop. An overlapping validation failure or cancellation can also clear a pending handler's context.Reproduction
Install
aws-lambda-powertools==3.34.0,pydantic, andhttpx, then run:Expected:
['0', '1', '2', '3', '4', '5']Observed:
['5', '5', '5', '5', '5', '5'], followed by the assertion failure.Cause and proposed fix
HttpResolverLocal.asgi_handler()assignsBaseRouter.current_eventandBaseRouter.lambda_context, then awaits resolution. Routing and validation also mutate a sharedself.contextdictionary. Validation middleware runs through a thread bridge, allowing another ASGI request to overwrite this state before the first consumes it. Request cleanup can clear another request's context.A request-scoped state object carried by
ContextVarcan isolate local ASGI resolution, including middleware threads, without serializing all local requests. I am preparing a focused PR with regressions for distinct bodies, overlapping validation failures, and cancellation.Scope
This concerns overlapping requests to the local ASGI server, not concurrent invocations within a Lambda execution environment. I understand the Lambda execution model; local ASGI servers nevertheless accept concurrent HTTP requests. This is separate from #8187 / #8196 (the validation-exception deadlock fixed in 3.29.0).
Environment
Python 3.13; Powertools 3.34.0 and current develop; local ASGI, no AWS resources required.