Files
code-center/src/modules/ws-proxy/manager.ts

88 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { nanoid } from 'nanoid';
import { WebSocket } from 'ws';
import { logger } from '../logger.ts';
import { EventEmitter } from 'eventemitter3';
class WsMessage {
ws: WebSocket;
user?: string;
emitter: EventEmitter;;
constructor({ ws, user }: WssMessageOptions) {
this.ws = ws;
this.user = user;
this.emitter = new EventEmitter();
}
async sendResponse(data: any) {
if (data.id) {
this.emitter.emit(data.id, data?.data);
}
}
async sendData(data: any, context?: any, opts?: { timeout?: number }) {
if (this.ws.readyState !== WebSocket.OPEN) {
return { code: 500, message: 'WebSocket is not open' };
}
const timeout = opts?.timeout || 10 * 6 * 1000; // 10 minutes
const id = nanoid();
const message = JSON.stringify({
id,
type: 'proxy',
data: {
message: data,
context: context || {},
},
});
logger.info('ws-proxy sendData', message);
this.ws.send(message);
const msg = { path: data?.path, key: data?.key, id: data?.id };
return new Promise((resolve) => {
const timer = setTimeout(() => {
resolve({
code: 500,
message: `运行超时执行的id: ${id},参数是${JSON.stringify(msg)}`,
});
}, timeout);
this.emitter.once(id, (data: any) => {
resolve(data);
clearTimeout(timer);
});
});
}
}
type WssMessageOptions = {
ws: WebSocket;
user?: string;
};
export class WsProxyManager {
wssMap: Map<string, WsMessage> = new Map();
constructor() { }
register(id: string, opts?: { ws: WebSocket; user: string }) {
if (this.wssMap.has(id)) {
const value = this.wssMap.get(id);
if (value) {
value.ws.close();
}
}
const [username, appId] = id.split('-');
const url = new URL(`/${username}/v1/${appId}`, 'https://kevisual.cn/');
console.log('WsProxyManager register', id, '访问地址', url.toString());
const value = new WsMessage({ ws: opts?.ws, user: opts?.user });
this.wssMap.set(id, value);
}
unregister(id: string) {
const value = this.wssMap.get(id);
if (value) {
value.ws.close();
}
this.wssMap.delete(id);
}
getIds(beginWith?: string) {
if (beginWith) {
return Array.from(this.wssMap.keys()).filter(key => key.startsWith(beginWith));
}
return Array.from(this.wssMap.keys());
}
get(id: string) {
return this.wssMap.get(id);
}
}