aio-libs / aio-libs/aiohttp-sse
SSE are batched
- Lingua principale
- Python
- Stelle
- 238
- Fork
- 37
- Merge medio
- 2m
- PR unite (30g)
- 1
Descrizione
Hi guys,
I've been trying to test aiohttp-sse with the [EventSource](https://www.dash-extensions.com/components/event_source) component in Dash. In a previous issue raised here, I failed to make it work since I forgot to include CORS handling. That is now solved, but I notice that the events arrive buffered to Dash. You can reproduce this with the following code.
```python
# server.py
from aiohttp import web
import json
import asyncio
from datetime import datetime
from aiohttp_sse import sse_response
import aiohttp_cors
app = web.Application()
routes = web.RouteTableDef()
cors = aiohttp_cors.setup(app, defaults={
"*": aiohttp_cors.ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_methods="*",
allow_headers="*",
max_age=3600
)
})
@routes.get("/hello")
async def hello(request: web.Request) -> web.StreamResponse:
async with sse_response(request) as resp:
while resp.is_connected():
services = json.dumps({
"time": f"Server Time : {datetime.now()}"
})
await resp.send(services)
await asyncio.sleep(1)
return resp
app.router.add_routes(routes)
for route in app.router.routes():
cors.add(route)
if __name__ == "__main__":
web.run_app(app, host='127.0.0.1', port=5000)
```
Now the Dash client:
```python
# client.py
from dash_extensions import EventSource
from dash_extensions.enrich import html, dcc, Output, Input, DashProxy
from dash.exceptions import PreventUpdate
import json
# Create small example app.
app = DashProxy(__name__)
app.layout = html.Div([
EventSource(id="sse", url="http://127.0.0.1:5000/hello"),
html.Span('SSE'),
html.Div(id="display")
])
@app.callback(
Output("display", "children"),
Input("sse", "message"),
)
def display(msg):
if msg is not None:
return msg
else:
raise PreventUpdate()
if __name__ == "__main__":
app.run_server(debug=True)
```
When I run these scripts, I get chucks like this in the `msg` variable in Dash:
```python
'{"time": "Server Time : 2024-04-05 09:44:52.022164"}\n{"time": "Server Time : 2024-04-05 09:44:53.023039"}\n{"time": "Server Time : 2024-04-05 09:44:54.023770"}\n{"time": "Server Time : 2024-04-05 09:44:55.025389"}\n{"time": "Server Time : 2024-04-05 09:44:56.027151"}\n{"time": "Server Time : 2024-04-05 09:44:57.029044"}\n{"time": "Server Time : 2024-04-05 09:44:58.030822"}\n{"time": "Server Time : 2024-04-05 09:44:59.032468"}\n{"time": "Server Time : 2024-04-05 09:45:00.033961"}\n{"time": "Server Time : 2024-04-05 09:45:01.035243"}\n{"time": "Server Time : 2024-04-05 09:45:02.036953"}\n{"time": "Server Time : 2024-04-05 09:45:03.038641"}\n{"time": "Server Time : 2024-04-05 09:45:04.040436"}\n{"time": "Server Time : 2024-04-05 09:45:05.041850"}\n{"time": "Server Time : 2024-04-05 09:45:06.043279"}'
```
Running the same thing in Starlette
```python
import asyncio
import json
from datetime import datetime
import uvicorn
from sse_starlette import EventSourceResponse
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
middleware = Middleware(CORSMiddleware, allow_origins=["*"], allow_headers=["*"])
server = Starlette(middleware=[middleware])
async def random_data():
while True:
await asyncio.sleep(1)
yield json.dumps({
"time": f"Server Time : {datetime.now()}"
})
@server.route("/hello")
async def sse(request):
generator = random_data()
return EventSourceResponse(generator)
if __name__ == "__main__":
uvicorn.run(server, port=5000)
```
gives atomic answers in the `msg` variable.
```python
{"time": "Server Time : 2024-04-05 11:04:50.266653"}
```
Note that, when I visit `http://127.0.0.1:5000/hello` after running the aiohttp-sse example, the events are received atomically, as expected.
So my question is, is there something in the transmission process that Starlette is doing and aiohttp-sse is omitting?
Please note that I would like to avoid the question of where is the bug (Dash EventSource or aiohttp-sse), since this easily leads to a kind of chicken-or-egg dilemma ... since their stuff works using the Starlette example. I'm just raising this here to see if you have any hint regarding this problem. I'm still resisting to switch to Starlette (or FastAPI) just because of this issue. Thanks in advance!
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.