@@ -10,10 +10,13 @@ import { JupyterMessage, ParsedIOMessage } from '../contracts'; |
10 | 10 | import { Helpers } from '../common/helpers'; |
11 | 11 | import * as Rx from 'rx'; |
12 | 12 | import { KernelRestartedError, KernelShutdownError } from '../common/errors'; |
| 13 | +import { OutputChannel } from 'vscode'; |
13 | 14 |
|
14 | 15 | export class JupyterSocketClient extends SocketCallbackHandler { |
15 | | - constructor(socketServer: SocketServer) { |
| 16 | + private isDebugging: boolean; |
| 17 | + constructor(socketServer: SocketServer, private outputChannel: OutputChannel) { |
16 | 18 | super(socketServer); |
| 19 | + this.isDebugging = process.env['DEBUG_DJAYAMANNE_IPYTHON'] === '1'; |
17 | 20 | this.registerCommandHandler(ResponseCommands.Pong, this.onPong.bind(this)); |
18 | 21 | this.registerCommandHandler(ResponseCommands.ListKernelsSpecs, this.onKernelsListed.bind(this)); |
19 | 22 | this.registerCommandHandler(ResponseCommands.Error, this.onError.bind(this)); |
@@ -30,7 +33,12 @@ export class JupyterSocketClient extends SocketCallbackHandler { |
30 | 33 | private idDispenser: IdDispenser; |
31 | 34 | private pid: number; |
32 | 35 | private guid: string; |
33 | | - |
| 36 | + private writeToDebugLog(message: string) { |
| 37 | + if (!this.isDebugging){ |
| 38 | + return; |
| 39 | + } |
| 40 | + this.outputChannel.appendLine(message); |
| 41 | + } |
34 | 42 | public dispose() { |
35 | 43 | super.dispose(); |
36 | 44 | } |
@@ -205,7 +213,7 @@ export class JupyterSocketClient extends SocketCallbackHandler { |
205 | 213 | const [def, id] = this.createId<string>(); |
206 | 214 | const observable = new Rx.Subject<ParsedIOMessage>(); |
207 | 215 | this.msgSubjectIndexedWithRunId.set(id, observable); |
208 | | - |
| 216 | + this.writeToDebugLog(`Send Code with Id = ${id}`); |
209 | 217 | this.SendRawCommand(Commands.RunCodeBytes); |
210 | 218 | this.stream.WriteString(id); |
211 | 219 | this.stream.WriteString(code); |
@@ -224,6 +232,7 @@ export class JupyterSocketClient extends SocketCallbackHandler { |
224 | 232 | if (typeof msg_id !== 'string') { |
225 | 233 | return; |
226 | 234 | } |
| 235 | + this.writeToDebugLog(`Code with Id = ${id} has msg_id = ${msg_id}`); |
227 | 236 | const def = this.pendingCommands.get(id); |
228 | 237 | this.releaseId(id); |
229 | 238 | def.resolve(msg_id); |
@@ -245,6 +254,7 @@ export class JupyterSocketClient extends SocketCallbackHandler { |
245 | 254 | } |
246 | 255 | const msg_type = message.header.msg_type; |
247 | 256 | if (msg_type === 'status') { |
| 257 | + this.writeToDebugLog(`Kernel Status = ${message.content.execution_state}`); |
248 | 258 | this.emit('status', message.content.execution_state); |
249 | 259 | } |
250 | 260 | const msg_id = message.parent_header.msg_id; |
@@ -278,21 +288,30 @@ export class JupyterSocketClient extends SocketCallbackHandler { |
278 | 288 | } |
279 | 289 | } |
280 | 290 | } |
| 291 | + this.writeToDebugLog(`Shell Result with msg_id = ${msg_id} with status = ${status}`); |
281 | 292 | if (!parsedMesage) { |
| 293 | + this.writeToDebugLog(`Shell Result with msg_id = ${msg_id} with status = ${status} ignored`); |
282 | 294 | return; |
283 | 295 | } |
| 296 | + this.writeToDebugLog(`Shell Result with msg_id = ${msg_id} has message of: '\n${jsonResult}`); |
284 | 297 | if (this.finalMessage.has(msg_id) && this.msgSubject.has(msg_id)) { |
285 | 298 | const subject = this.msgSubject.get(msg_id); |
286 | 299 | const info = this.finalMessage.get(msg_id); |
| 300 | + this.writeToDebugLog(`Shell Result with msg_id = ${msg_id} found in finalMessage and msgSubject`); |
287 | 301 | // If th io message with status='idle' has been received, that means message execution is deemed complete |
288 | 302 | if (info.ioStatusSent) { |
| 303 | + this.writeToDebugLog(`Shell Result with msg_id = ${msg_id} found in finalMessage and msgSubject, and ioStatusSent = true`); |
289 | 304 | this.finalMessage.delete(msg_id); |
290 | 305 | this.msgSubject.delete(msg_id); |
291 | 306 | subject.onNext(parsedMesage); |
292 | 307 | subject.onCompleted(); |
293 | 308 | } |
| 309 | + else { |
| 310 | + this.writeToDebugLog(`Shell Result with msg_id = ${msg_id} found in finalMessage and msgSubject, and ioStatusSent = false`); |
| 311 | + } |
294 | 312 | } |
295 | 313 | else { |
| 314 | + this.writeToDebugLog(`Shell Result with msg_id = ${msg_id} not found in finalMessage or not found in msgSubject`); |
296 | 315 | // Wait for the io message with status='idle' to arrive |
297 | 316 | const info = this.finalMessage.has(msg_id) ? this.finalMessage.get(msg_id) : { ioStatusSent: false }; |
298 | 317 | info.shellMessage = parsedMesage; |
@@ -316,41 +335,52 @@ export class JupyterSocketClient extends SocketCallbackHandler { |
316 | 335 | } |
317 | 336 | const msg_type = message.header.msg_type; |
318 | 337 | if (msg_type === 'status') { |
| 338 | + this.writeToDebugLog(`io Kernel Status = ${message.content.execution_state}`); |
319 | 339 | this.emit('status', message.content.execution_state); |
320 | 340 | } |
321 | 341 | const msg_id = message.parent_header.msg_id; |
322 | 342 | if (!msg_id) { |
323 | 343 | return; |
324 | 344 | } |
| 345 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id}`); |
325 | 346 |
|
326 | 347 | // Ok, if we have received a status of 'idle' this means the execution has completed |
327 | 348 | if (msg_type === 'status' && message.content.execution_state === 'idle') { |
| 349 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle`); |
328 | 350 | let timesWaited = 0; |
329 | 351 | const waitForFinalIOMessage = () => { |
330 | 352 | timesWaited += 1; |
331 | 353 | // The Shell message handler has processed the message |
332 | 354 | if (!this.msgSubject.has(msg_id)) { |
| 355 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle, not yet in msgSubject`); |
333 | 356 | return; |
334 | 357 | } |
335 | 358 | // Last message sent on shell channel (status='ok' or status='error') |
336 | 359 | // and now we have a status message, this means the exection is deemed complete |
337 | 360 | if (this.finalMessage.has(msg_id)) { |
| 361 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle, found in finalMessage`); |
338 | 362 | const subject = this.msgSubject.get(msg_id); |
339 | 363 | const info = this.finalMessage.get(msg_id); |
340 | 364 | if (!info.shellMessage && timesWaited < 10) { |
| 365 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle, found in finalMessage and info.shellMessage = ` + typeof (info.shellMessage)); |
| 366 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle, found in finalMessage and timesWaited = ` + timesWaited.toString()); |
341 | 367 | setTimeout(() => { |
342 | 368 | waitForFinalIOMessage(); |
343 | 369 | }, 10); |
344 | 370 | return; |
345 | 371 | } |
346 | 372 | this.finalMessage.delete(msg_id); |
347 | 373 | this.msgSubject.delete(msg_id); |
| 374 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle almost done`); |
348 | 375 | if (info.shellMessage) { |
| 376 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle, and shell message being sent out`); |
349 | 377 | subject.onNext(info.shellMessage); |
350 | 378 | } |
| 379 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle, done`); |
351 | 380 | subject.onCompleted(); |
352 | 381 | } |
353 | 382 | else { |
| 383 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} and msg_type == status and execution_state == idle, inserted into finalMessage`); |
354 | 384 | this.finalMessage.set(msg_id, { ioStatusSent: true }); |
355 | 385 | } |
356 | 386 | }; |
@@ -366,9 +396,11 @@ export class JupyterSocketClient extends SocketCallbackHandler { |
366 | 396 | return; |
367 | 397 | } |
368 | 398 | if (this.msgSubject.has(msg_id)) { |
| 399 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} found in msgSubject`); |
369 | 400 | this.msgSubject.get(msg_id).onNext(parsedMesage); |
370 | 401 | } |
371 | 402 | else { |
| 403 | + this.writeToDebugLog(`iopub with msg_id = ${msg_id} not found in msgSubject and inserted into unhandledMessages`); |
372 | 404 | let data = []; |
373 | 405 | if (this.unhandledMessages.has(msg_id)) { |
374 | 406 | data = this.unhandledMessages.get(msg_id); |
|