1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
const WebSocket = require("ws");
import fetch from "node-fetch";
export abstract class Messenger {
abstract send(messageType: string, data: object): void;
abstract onMessageType(
messageType: string,
callback: (data: object) => void
): void;
abstract onMessage(callback: (messageType: string, data: any) => void): void;
abstract onOpen(callback: () => void): void;
abstract onClose(callback: () => void): void;
abstract onError(callback: () => void): void;
abstract sendAndReceive(messageType: string, data: any): Promise<any>;
abstract close(): void;
}
export class WebsocketMessenger extends Messenger {
websocket: WebSocket;
private onMessageListeners: {
[messageType: string]: ((data: object) => void)[];
} = {};
private onOpenListeners: (() => void)[] = [];
private onCloseListeners: (() => void)[] = [];
private onErrorListeners: (() => void)[] = [];
private serverUrl: string;
_newWebsocket(): WebSocket {
// // Dynamic import, because WebSocket is builtin with browser, but not with node. And can't use require in browser.
// if (typeof process === "object") {
// console.log("Using node");
// // process is only available in Node
// var WebSocket = require("ws");
// }
const newWebsocket = new WebSocket(this.serverUrl);
for (const listener of this.onOpenListeners) {
this.onOpen(listener);
}
for (const listener of this.onCloseListeners) {
this.onClose(listener);
}
for (const listener of this.onErrorListeners) {
this.onError(listener);
}
for (const messageType in this.onMessageListeners) {
for (const listener of this.onMessageListeners[messageType]) {
this.onMessageType(messageType, listener);
}
}
newWebsocket.addEventListener("open", () => console.log("Websocket connection opened"));
newWebsocket.addEventListener("error", (error: any) => {
console.error("Websocket error occurred: ", error);
});
newWebsocket.addEventListener("close", (error: any) => {
console.log("Websocket connection closed: ", error);
});
return newWebsocket;
}
async checkServerRunning(serverUrl: string): Promise<boolean> {
// Check if already running by calling /health
try {
const response = await fetch(serverUrl + "/health");
if (response.status === 200) {
console.log("Continue python server already running");
return true;
} else {
return false;
}
} catch (e) {
return false;
}
}
constructor(serverUrl: string) {
super();
this.serverUrl = serverUrl;
this.websocket = this._newWebsocket();
// Wait until the server is running
// const interval = setInterval(async () => {
// if (
// await this.checkServerRunning(
// serverUrl.replace("/ide/ws", "").replace("ws://", "http://")
// )
// ) {
// this.websocket = this._newWebsocket();
// clearInterval(interval);
// } else {
// console.log(
// "Waiting for python server to start-----------------------"
// );
// }
// }, 1000);
// const interval = setInterval(() => {
// if (this.websocket.readyState === this.websocket.OPEN) {
// clearInterval(interval);
// } else if (this.websocket.readyState !== this.websocket.CONNECTING) {
// this.websocket = this._newWebsocket();
// }
// }, 1000);
}
send(messageType: string, data: object) {
const payload = JSON.stringify({ messageType, data });
if (this.websocket.readyState === this.websocket.OPEN) {
this.websocket.send(payload);
} else {
if (this.websocket.readyState !== this.websocket.CONNECTING) {
this.websocket = this._newWebsocket();
}
this.websocket.addEventListener("open", () => {
this.websocket.send(payload);
});
}
}
sendAndReceive(messageType: string, data: any): Promise<any> {
return new Promise((resolve, reject) => {
const eventListener = (data: any) => {
// THIS ISN"T GETTING CALLED
resolve(data);
this.websocket.removeEventListener("message", eventListener);
};
this.onMessageType(messageType, eventListener);
this.send(messageType, data);
});
}
onMessageType(messageType: string, callback: (data: any) => void): void {
this.websocket.addEventListener("message", (event: any) => {
const msg = JSON.parse(event.data);
if (msg.messageType === messageType) {
callback(msg.data);
}
});
}
onMessage(
callback: (
messageType: string,
data: any,
messenger: WebsocketMessenger
) => void
): void {
this.websocket.addEventListener("message", (event) => {
const msg = JSON.parse(event.data);
callback(msg.messageType, msg.data, this);
});
}
onOpen(callback: () => void): void {
this.websocket.addEventListener("open", callback);
}
onClose(callback: () => void): void {
this.websocket.addEventListener("close", callback);
}
onError(callback: () => void): void {
this.websocket.addEventListener("error", callback);
}
close(): void {
this.websocket.close();
}
}
|