fix: auto retry of active ws

This commit is contained in:
Wesley F. Young 2024-08-12 02:12:09 +08:00
parent 4e85124aeb
commit 6785922379

View File

@ -1,7 +1,6 @@
import { IOB11NetworkAdapter, OB11EmitEventContent } from '@/onebot/network/index'; import { IOB11NetworkAdapter, OB11EmitEventContent } from '@/onebot/network/index';
import { WebSocket } from 'ws'; import { WebSocket } from 'ws';
import BaseAction from '@/onebot/action/BaseAction'; import BaseAction from '@/onebot/action/BaseAction';
import { sleep } from '@/common/utils/helper';
import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent'; import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent';
import { NapCatCore } from '@/core'; import { NapCatCore } from '@/core';
import { NapCatOneBot11Adapter } from '../main'; import { NapCatOneBot11Adapter } from '../main';
@ -19,7 +18,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
logger: LogWrapper; logger: LogWrapper;
private connection: WebSocket | null = null; private connection: WebSocket | null = null;
private actionMap: Map<string, BaseAction<any, any>> = new Map(); private actionMap: Map<string, BaseAction<any, any>> = new Map();
private heartbeatTimer: NodeJS.Timeout | null = null; private heartbeatRef: NodeJS.Timeout | null = null;
private readonly token: string; private readonly token: string;
constructor(url: string, reconnectIntervalInMillis: number, heartbeatInterval: number, token:string, coreContext: NapCatCore, onebotContext: NapCatOneBot11Adapter) { constructor(url: string, reconnectIntervalInMillis: number, heartbeatInterval: number, token:string, coreContext: NapCatCore, onebotContext: NapCatOneBot11Adapter) {
@ -50,6 +49,11 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
if (this.connection) { if (this.connection) {
return; return;
} }
this.heartbeatRef = setInterval(() => {
if (this.connection && this.connection.readyState === WebSocket.OPEN) {
this.connection.send(JSON.stringify(new OB11HeartbeatEvent(this.coreContext, this.heartbeatInterval, this.coreContext.selfInfo.online, true)));
}
}, this.heartbeatInterval);
await this.tryConnect(); await this.tryConnect();
} }
@ -64,19 +68,9 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
this.connection.close(); this.connection.close();
this.connection = null; this.connection = null;
} }
if (this.heartbeatTimer) { if (this.heartbeatRef) {
clearInterval(this.heartbeatTimer); clearInterval(this.heartbeatRef);
this.heartbeatTimer = null; this.heartbeatRef = null;
}
}
private registerHeartBeat() {
if (this.connection) {
this.heartbeatTimer = setInterval(() => {
if (this.connection && this.connection.readyState === WebSocket.OPEN) {
this.connection.send(JSON.stringify(new OB11HeartbeatEvent(this.coreContext, this.heartbeatInterval, this.coreContext.selfInfo.online, true)));
}
}, this.heartbeatInterval);
} }
} }
@ -87,31 +81,40 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
} }
private async tryConnect() { private async tryConnect() {
while (!this.connection && !this.isClosed) { if (!this.connection && !this.isClosed) {
try { let isClosedByError = false;
this.connection = new WebSocket(this.url, {
headers: { this.connection = new WebSocket(this.url, {
'X-Self-ID': this.coreContext.selfInfo.uin, headers: {
'Authorization': `Bearer ${this.token}`, 'X-Self-ID': this.coreContext.selfInfo.uin,
'x-client-role': 'Universal', // koishi-adapter-onebot 需要这个字段 'Authorization': `Bearer ${this.token}`,
'User-Agent': 'OneBot/11', 'x-client-role': 'Universal', // koishi-adapter-onebot 需要这个字段
} 'User-Agent': 'OneBot/11',
}); },
this.connection.on('message', (data) => {
this.handleMessage(data); });
}); this.connection.on('message', (data) => {
this.connection.once('close', () => { this.handleMessage(data);
});
this.connection.once('close', () => {
if (!isClosedByError) {
this.logger.logError(`反向WebSocket (${this.url}) 连接意外关闭`);
this.logger.logError(`${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
if (!this.isClosed) { if (!this.isClosed) {
this.connection = null; this.connection = null;
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis); setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
} }
}); }
this.registerHeartBeat(); });
} catch (e) { this.connection.on('error', (err) => {
this.connection = null; isClosedByError = true;
console.log('Failed to connect to the server, retrying in 5 seconds...'); this.logger.logError(`反向WebSocket (${this.url}) 连接错误`, err);
await sleep(5000); this.logger.logError(`${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
} if (!this.isClosed) {
this.connection = null;
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
}
});
} }
} }