Skip to content

Commit

Permalink
fix: 🐛 SocketStore add debugger-online event to flush cache
Browse files Browse the repository at this point in the history
  • Loading branch information
wqcstrong committed Mar 8, 2023
1 parent 1d7b0cf commit e07428e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 51 deletions.
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export default class PageSpy {
// Debug client url origin
private clientOrigin = '';

private socketStore = socketStore;

constructor(init: InitConfig) {
const config = mergeConfig(init);
const { api, clientOrigin } = config;
Expand Down
108 changes: 58 additions & 50 deletions src/utils/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,37 @@ class SocketStore {
// websocket instance
socket: WebSocket | null = null;

socketUrl: string = '';

socketConnection: SpySocket.Connection | null = null;

pingTimer: number | null = null;
timer: number | null = null;

reconnectTimes = 3;

// messages store
messages: (SpySocket.BrodcastEvent | SpySocket.UnicastEvent)[] = [];

// Don't try to reconnect if error occupied
reconnectable: boolean = true;

// indicated connected whether or not
isInited: boolean = false;
connectionStatus: boolean = false;

// events center
events: Record<SpyMessage.InteractiveType, SocketEventCallback[]> = {
refresh: [],
debug: [],
'atom-detail': [],
'atom-getter': [],
'debugger-online': [],
};

constructor() {
this.addListener('debug', SocketStore.handleDebugger);
this.addListener('atom-detail', SocketStore.handleResolveAtom);
this.addListener('atom-getter', SocketStore.handleAtomPropertyGetter);
this.addListener('debugger-online', this.handleFlushBuffer);
}

init(url: string) {
Expand All @@ -64,41 +71,46 @@ class SocketStore {
throw Error('WebSocket 连接 URL 不可缺省');
}
this.socket = new WebSocket(url);
this.socketUrl = url;
this.socket.addEventListener('open', () => {
this.isInited = true;
this.keepConnect();
this.connectOnline();
this.peelMessage();
});
this.socket.addEventListener('close', () => {
this.isInited = false;
if (this.pingTimer) {
window.clearInterval(this.pingTimer);
}
this.tryReconnect();
this.connectOffline();
});
this.socket.addEventListener('error', () => {
this.isInited = false;
this.socket = null;
throw Error('WebSocket 连接失败');
this.reconnectable = false;
this.connectOffline();
throw new Error('WebSocket connect fail');
});
} catch (e: any) {
alert(`[PageSpy] ${e.message}`);
}
}

connectOnline() {
this.connectionStatus = true;
this.reconnectTimes = 3;
this.pingConnect();
}

connectOffline() {
this.socket = null;
this.connectionStatus = false;
this.socketConnection = null;
this.clearPing();
if (!this.reconnectable) {
return;
}
this.tryReconnect();
}

tryReconnect() {
if (this.reconnectTimes > 0) {
this.reconnectTimes -= 1;
if (this.socket!.readyState !== WebSocket.OPEN) {
setTimeout(() => {
this.init(this.socket!.url);
}, 1000);
}
this.init(this.socketUrl);
} else {
this.socket = null;
if (this.pingTimer) {
window.clearInterval(this.pingTimer);
}
sessionStorage.setItem(
'page-spy-room',
JSON.stringify({ usable: false }),
Expand All @@ -107,8 +119,8 @@ class SocketStore {
}
}

keepConnect() {
this.pingTimer = window.setInterval(() => {
pingConnect() {
this.timer = window.setInterval(() => {
if (this.socket?.readyState !== WebSocket.OPEN) return;
this.send({
type: 'ping',
Expand All @@ -117,6 +129,12 @@ class SocketStore {
}, 10000);
}

clearPing() {
if (this.timer) {
window.clearInterval(this.timer);
}
}

// get the data which we expected from nested structure of the message
private peelMessage() {
if (this.socket) {
Expand All @@ -128,15 +146,6 @@ class SocketStore {
const { selfConnection } = result.content;
this.socketConnection = selfConnection;
break;
case 'join':
const { address } = result.content.connection;
if (
this.socketConnection &&
this.socketConnection.address !== address
) {
this.sendBuffer(result.content.connection);
}
break;
case 'send':
const { data, from, to } = result.content;
if (to.address !== this.socketConnection?.address) return;
Expand All @@ -146,6 +155,7 @@ class SocketStore {
to,
});
break;
case 'join':
case 'ping':
case 'leave':
case 'close':
Expand Down Expand Up @@ -173,39 +183,36 @@ class SocketStore {
});
}

/**
* unicast
* @param msg message
* @param to target address
*/
unicastMessage(msg: SpyMessage.MessageItem, to: SpySocket.Connection) {
const message = makeUnicastMessage(msg, this.socketConnection!, to);
this.send(message);
}

/**
* boradcast
* @param msg message
*/
broadcastMessage(msg: SpyMessage.MessageItem, isCache: boolean = false) {
const message = makeBroadcastMessage(msg);
this.send(message, isCache);
}

private sendBuffer(to: SpySocket.Connection) {
this.messages.forEach(
(msg: SpySocket.BrodcastEvent | SpySocket.UnicastEvent) => {
handleFlushBuffer(message: SocketEvent<{ latestId: string }>) {
const { latestId } = message.source.data;

const msgIndex = this.messages.findIndex(
(i) => i.content.data.data.id === latestId,
);

this.messages
.slice(msgIndex + 1)
.forEach((msg: SpySocket.BrodcastEvent | SpySocket.UnicastEvent) => {
const data = {
type: 'send',
content: {
data: msg.content.data,
from: this.socketConnection!,
to,
to: message.from,
},
} as const;
this.send(data, true);
},
);
});
}

// run excutable code which received from remote and send back the result
Expand Down Expand Up @@ -284,7 +291,7 @@ class SocketStore {
}

send(msg: SpySocket.ClientEvent, isCache: boolean = false) {
if (this.isInited) {
if (this.connectionStatus) {
try {
this.socket?.send(stringifyData(msg));
} catch (e) {
Expand All @@ -299,9 +306,10 @@ class SocketStore {
}

close() {
if (this.pingTimer) {
window.clearInterval(this.pingTimer);
if (this.timer) {
window.clearInterval(this.timer);
}
this.reconnectable = false;
this.socket?.close();
}
}
Expand Down
3 changes: 2 additions & 1 deletion types/lib/message-type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export type InteractiveType =
| 'debug'
| 'refresh'
| 'atom-detail'
| 'atom-getter';
| 'atom-getter'
| 'debugger-online';

export interface MessageItem {
role: 'client' | 'debugger';
Expand Down

0 comments on commit e07428e

Please sign in to comment.