first commit
This commit is contained in:
commit
3c0479faf0
169 files changed
+27617
No files matched your search
@@ -0,0 +1,65 @@
|
||||
import { PassThrough } from 'node:stream'
|
||||
import type { HttpContext } from '@adonisjs/core/http'
|
||||
|
||||
export interface SseChannel {
|
||||
/**
|
||||
* Sends one event to the browser. Ignored once the connection is closed.
|
||||
*/
|
||||
send(event: string, data: unknown): void
|
||||
|
||||
/**
|
||||
* Registers a callback invoked once, when the browser disconnects or the
|
||||
* channel is closed by the server.
|
||||
*/
|
||||
onClose(callback: () => void): void
|
||||
|
||||
close(): void
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the response into a Server-Sent Events stream (used with
|
||||
* EventSource on the Angular side for the live metrics, logs and jobs).
|
||||
*/
|
||||
export function openSse({ response }: HttpContext): SseChannel {
|
||||
const stream = new PassThrough()
|
||||
const closeCallbacks: (() => void)[] = []
|
||||
let closed = false
|
||||
|
||||
response.header('Content-Type', 'text/event-stream; charset=utf-8')
|
||||
response.header('Cache-Control', 'no-cache, no-transform')
|
||||
response.header('Connection', 'keep-alive')
|
||||
response.header('X-Accel-Buffering', 'no')
|
||||
response.stream(stream)
|
||||
|
||||
/**
|
||||
* Comments keep the connection open through Caddy and let the browser
|
||||
* know quickly that the stream is established.
|
||||
*/
|
||||
stream.write('retry: 5000\n\n')
|
||||
const heartbeat = setInterval(() => stream.write(': ping\n\n'), 25_000)
|
||||
|
||||
const close = () => {
|
||||
if (closed) return
|
||||
closed = true
|
||||
clearInterval(heartbeat)
|
||||
for (const callback of closeCallbacks) callback()
|
||||
stream.end()
|
||||
}
|
||||
|
||||
/**
|
||||
* "close" on the response (not the request) is emitted when the browser
|
||||
* goes away.
|
||||
*/
|
||||
response.response.on('close', close)
|
||||
|
||||
return {
|
||||
send(event, data) {
|
||||
if (closed) return
|
||||
stream.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`)
|
||||
},
|
||||
onClose(callback) {
|
||||
closeCallbacks.push(callback)
|
||||
},
|
||||
close,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user