bfcache: server - Implement WebSocket server functionality
* Added WebSocketServer class with configurable options * Introduced WebSocketServerFactory for creating WebSocket relay servers * Updated index.ts to set up a server with WebSocket support and handle various signals for graceful shutdown
This commit is contained in:
@@ -1 +1,36 @@
|
|||||||
console.log('hello claris');
|
import {LoggerFactory} from '@techniker-me/logger';
|
||||||
|
import WebSocketServerFactory from './net/websockets/WebSocketServerFactory';
|
||||||
|
|
||||||
|
LoggerFactory.setLoggingLevel('All');
|
||||||
|
|
||||||
|
const webSocketRelayServer = WebSocketServerFactory.createWebSocketRelayServer();
|
||||||
|
const PORT = parseInt(process.env.PORT || '4444', 10);
|
||||||
|
|
||||||
|
const server = Bun.serve({
|
||||||
|
port: PORT,
|
||||||
|
fetch: (request, server) => {
|
||||||
|
if (server.upgrade(request)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response('hi');
|
||||||
|
},
|
||||||
|
websocket: webSocketRelayServer
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('SIGINT', () => {
|
||||||
|
console.log('Received [SIGINT] stopping server');
|
||||||
|
server.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('SIGKILL', () => {
|
||||||
|
console.log('Received [SIGKILL] stopping server');
|
||||||
|
server.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('SIGTERM', () => {
|
||||||
|
console.log('Received [SIGTERM] stopping server');
|
||||||
|
server.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Server listening on [:${server.port}]`);
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import type {ServerWebSocket, WebSocketCompressor} from 'bun';
|
import type {ServerWebSocket, WebSocketCompressor} from 'bun';
|
||||||
import type {Seconds, Bytes} from './types/Units';
|
import type {Seconds, Bytes} from '../../types/Units';
|
||||||
|
|
||||||
export type PerMessageDeflate =
|
export type PerMessageDeflate =
|
||||||
| boolean
|
| boolean
|
||||||
| {
|
| {
|
||||||
compress?: boolean | WebSocketCompressor;
|
compress?: boolean | WebSocketCompressor;
|
||||||
decomporess?: boolean | WebSocketCompressor;
|
decomporess?: boolean | WebSocketCompressor;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WebSocketServerOptions = {
|
export type WebSocketServerOptions = {
|
||||||
maxPayloadLength?: Bytes;
|
maxPayloadLength?: Bytes;
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import {LoggerFactory} from '@techniker-me/logger';
|
||||||
|
import WebSocketServer, {WebSocketServerOptions} from './WebSocketServer';
|
||||||
|
import {ServerWebSocket} from 'bun';
|
||||||
|
|
||||||
|
export default class WebSocketServerFactory {
|
||||||
|
public static createWebSocketRelayServer(): WebSocketServer {
|
||||||
|
const logger = LoggerFactory.getLogger('WebSocketRelayServer');
|
||||||
|
const clients = new Set<ServerWebSocket>();
|
||||||
|
const webSocketRelayServerOptions: WebSocketServerOptions = {
|
||||||
|
onSocketError: (client, error) => logger.error(`Error: [%o] [${error.message}]`, client),
|
||||||
|
onSocketOpen: client => {
|
||||||
|
logger.debug('New WebSocketClient [%o]', client);
|
||||||
|
|
||||||
|
clients.add(client);
|
||||||
|
},
|
||||||
|
onSocketMessage: (fromClient, message) => {
|
||||||
|
logger.debug(`Relaying message [%o]`, message);
|
||||||
|
|
||||||
|
for (const client of clients) {
|
||||||
|
if (client === fromClient) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.send(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSocketClose: client => clients.delete(client),
|
||||||
|
onSocketDrain: client => logger.debug('Client drain [%o]', client),
|
||||||
|
publishToSelf: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return new WebSocketServer(webSocketRelayServerOptions);
|
||||||
|
}
|
||||||
|
private constructor() {
|
||||||
|
throw new Error('WebSocketServerFactory is a static class that may not be instantiated');
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user