Setting up Server-Sent events is relatively simple - especially using FastAPI - you can do something like this:
def fake_data_streamer():
for i in range(10):
yield "some streamed data"
time.sleep(0.5)
@app.get('/')
async def main():
return StreamingResponse(fake_data_streamer())
And upon an HTTP GET, the connection will return "some streamed data" every 0.5 seconds.
What if I wanted to stream some structured data though, like JSON?
For example, I want the data to be JSON, so something like:
def fake_data_streamer():
for i in range(10):
yield json.dumps({'result': 'a lot of streamed data', "seriously": ["so", "much", "data"]}, indent=4)
time.sleep(0.5)
Is this a proper server side implementation? Does this pose a risk of the client receiving partially formed payloads - which is fine in the plaintext case, but makes the JSON un-parseable?
If this is okay, how would you read this from the client side? Something like this:
async def main():
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
while True:
chunk = await resp.content.readuntil(b"\n")
await asyncio.sleep(1)
if not chunk:
break
print(chunk)
Although I am not sure what the proper separator / reading mode is appropriate to ensure that the client always receives fully formed JSON events.
Or, is this a completely improper way to accomplish streaming of fully formed JSON events.
For reference, OpenAI achieves streaming of complete JSON objects in their API: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb