@@ -15,6 +15,8 @@ export class BrowserAgentIpc {
15
15
private static instance : BrowserAgentIpc ;
16
16
public onMessageReceived : ( ( message : WebSocketMessageV2 ) => void ) | null ;
17
17
private webSocket : any ;
18
+ private reconnectionPending : boolean = false ;
19
+ private webSocketPromise : Promise < WebSocket | undefined > | null = null ;
18
20
19
21
private constructor ( ) {
20
22
this . webSocket = null ;
@@ -30,65 +32,86 @@ export class BrowserAgentIpc {
30
32
} ;
31
33
32
34
public async ensureWebsocketConnected ( ) {
33
- return new Promise < WebSocket | undefined > ( async ( resolve ) => {
34
- if ( this . webSocket ) {
35
- if ( this . webSocket . readyState === WebSocket . OPEN ) {
36
- resolve ( this . webSocket ) ;
35
+ // if there's a pending websocket promise, return it
36
+ if ( this . webSocketPromise ) {
37
+ return this . webSocketPromise ;
38
+ }
39
+
40
+ //create a new promise to establish the websocket connection
41
+ this . webSocketPromise = new Promise < WebSocket | undefined > (
42
+ async ( resolve ) => {
43
+ if ( this . webSocket ) {
44
+ if ( this . webSocket . readyState === WebSocket . OPEN ) {
45
+ resolve ( this . webSocket ) ;
46
+ return ;
47
+ }
48
+ try {
49
+ this . webSocket . close ( ) ;
50
+ this . webSocket = undefined ;
51
+ } catch { }
52
+ }
53
+
54
+ this . webSocket = await createWebSocket (
55
+ "browser" ,
56
+ "client" ,
57
+ "inlineBrowser" ,
58
+ ) ;
59
+ if ( ! this . webSocket ) {
60
+ resolve ( undefined ) ;
37
61
return ;
38
62
}
39
- try {
40
- this . webSocket . close ( ) ;
41
- this . webSocket = undefined ;
42
- } catch { }
43
- }
44
63
45
- this . webSocket = await createWebSocket (
46
- "browser" ,
47
- "client" ,
48
- "inlineBrowser" ,
49
- ) ;
50
- if ( ! this . webSocket ) {
51
- resolve ( undefined ) ;
52
- return ;
53
- }
64
+ this . webSocket . binaryType = "blob" ;
65
+ keepWebSocketAlive ( this . webSocket , "browser" ) ;
66
+
67
+ this . webSocket . onmessage = async ( event : any ) => {
68
+ const text =
69
+ typeof event . data === "string"
70
+ ? event . data
71
+ : await ( event . data as Blob ) . text ( ) ;
72
+ try {
73
+ const data = JSON . parse ( text ) as WebSocketMessageV2 ;
74
+
75
+ let schema = data . method ?. split ( "/" ) [ 0 ] ;
76
+ schema = schema || "browser" ;
77
+
78
+ if (
79
+ ( schema == "browser" ||
80
+ schema == "webAgent" ||
81
+ schema . startsWith ( "browser." ) ) &&
82
+ this . onMessageReceived
83
+ ) {
84
+ debugBrowserIPC ( "Browser -> Dispatcher" , data ) ;
85
+ this . onMessageReceived ( data ) ;
86
+ }
87
+ } catch { }
88
+ } ;
89
+
90
+ this . webSocket . onclose = ( ) => {
91
+ console . log ( "websocket connection closed" ) ;
92
+ this . webSocket = undefined ;
93
+ this . reconnectWebSocket ( ) ;
94
+ } ;
54
95
55
- this . webSocket . binaryType = "blob" ;
56
- keepWebSocketAlive ( this . webSocket , "browser" ) ;
57
-
58
- this . webSocket . onmessage = async ( event : any ) => {
59
- const text =
60
- typeof event . data === "string"
61
- ? event . data
62
- : await ( event . data as Blob ) . text ( ) ;
63
- try {
64
- const data = JSON . parse ( text ) as WebSocketMessageV2 ;
65
-
66
- let schema = data . method ?. split ( "/" ) [ 0 ] ;
67
- schema = schema || "browser" ;
68
-
69
- if (
70
- ( schema == "browser" ||
71
- schema == "webAgent" ||
72
- schema . startsWith ( "browser." ) ) &&
73
- this . onMessageReceived
74
- ) {
75
- debugBrowserIPC ( "Browser -> Dispatcher" , data ) ;
76
- this . onMessageReceived ( data ) ;
77
- }
78
- } catch { }
79
- } ;
96
+ this . webSocketPromise = null ;
80
97
81
- this . webSocket . onclose = ( ) => {
82
- console . log ( "websocket connection closed" ) ;
83
- this . webSocket = undefined ;
84
- this . reconnectWebSocket ( ) ;
85
- } ;
98
+ resolve ( this . webSocket ) ;
99
+ } ,
100
+ ) ;
86
101
87
- resolve ( this . webSocket ) ;
88
- } ) ;
102
+ return this . webSocketPromise ;
89
103
}
90
104
91
105
private reconnectWebSocket ( ) {
106
+ // if there is a reconnection pending just return
107
+ if ( this . reconnectionPending ) {
108
+ return ;
109
+ }
110
+
111
+ // indicate a reconnection attempt is pending
112
+ this . reconnectionPending = true ;
113
+
114
+ // attempt reconnection every 5 seconds
92
115
const connectionCheckIntervalId = setInterval ( async ( ) => {
93
116
if (
94
117
this . webSocket &&
@@ -100,6 +123,9 @@ export class BrowserAgentIpc {
100
123
console . log ( "Retrying connection" ) ;
101
124
await this . ensureWebsocketConnected ( ) ;
102
125
}
126
+
127
+ // reconnection was either successful or attempted
128
+ this . reconnectionPending = false ;
103
129
} , 5 * 1000 ) ;
104
130
}
105
131
0 commit comments