Could the events be grouped in some way? Store groups of events per write request
Could the events be grouped in some way? Store groups of events per write request

... dropdown. I reported as soon as I saw it. Someone at Cloudflare deleted soon after my report.@lumenize/proxy-fetchimport { DurableObject } from "cloudflare:workers"
export default {
async fetch(request, env, ctx): Promise<Response> {
const stub = env.MY_DURABLE_OBJECT.getByName("foo");
if (request.url.includes('/subscribe')) return stub.subscribe(request)
else if (request.url.includes('/message')) return await stub.message(request)
else return new Response(html, {headers: {'content-type': 'text/html'}})
},
} satisfies ExportedHandler<Env>const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Durable Object SSE Test</title>
</head>
<body>
<h1>New Durable Object SSE Test</h1>
<button id="send">Send Message</button>
<div id="log" style="margin-top: 1em; white-space: pre;"></div>
<script>
const log = (msg) => {
const el = document.getElementById('log');
el.textContent += msg + "\\n";
};
// Subscribe to the stream
const es = new EventSource('/subscribe');
es.onopen = () => log('[connected]');
es.onerror = (err) => log('[error] ' + JSON.stringify(err));
es.onmessage = (e) => log('[message] ' + e.data);
// Send a message to broadcast
document.getElementById('send').addEventListener('click', async () => {
const res = await fetch('/message', {
method: 'POST',
body: JSON.stringify({ time: new Date().toISOString() }),
headers: { 'Content-Type': 'application/json' }
});
log('[sent] ' + (await res.text()));
});
</script>
</body>
</html>
`export class MyDurableObject extends DurableObject<Env> {
encoder = new TextEncoder()
writers: Map<string, WritableStreamDefaultWriter<Uint8Array>> = new Map()
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
}
subscribe(request: Request): Response {
const stream = new IdentityTransformStream()
const writer = stream.writable.getWriter()
const id = crypto.randomUUID()
this.writers.set(id, writer)
const headers = {
'Connection': 'keep-alive',
'Cache-Control': 'no-cache',
'Content-Type': 'text/event-stream',
'Access-Control-Allow-Origin': request.headers.get('Origin')!, // secured @ worker (outside world portal)
}
// initial comment
writer.write(this.encoder.encode(`: connected\n\n`))
// clean up on abort
request.signal.addEventListener('abort', () => {
writer.close()
this.writers.delete(id)
})
return new Response(stream.readable, { headers })
}
async message(request: Request): Promise<Response> {
const data = await request.text()
for (const [_, writer] of this.writers) {
writer.write(this.encoder.encode(`data: ${data}\n\n`))
}
return new Response('good', {
status: 200,
headers: {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Origin': request.headers.get('Origin')!,
},
})
}
}