From 3c5600811da9d830a4955486c10f037b7e7d429e Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 13 Jun 2022 18:11:11 +0200 Subject: [PATCH 1/5] test interval for output panel --- .../src/node/core-service-impl.ts | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index 00d6ca5ed..a6b48a972 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -39,6 +39,25 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { protected uploading = false; + private outputString: string; + + private FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS = 32; + + private flushOutputMessagesInterval?: NodeJS.Timeout; + + setOutputMessagesInterval(): void { + this.flushOutputMessagesInterval = setInterval(() => { + this.responseService.appendToOutput({ + chunk: this.outputString, + }); + }, this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS); + } + + clearOutputMessagesInterval(): void { + clearInterval(this.flushOutputMessagesInterval); + this.flushOutputMessagesInterval = undefined; + } + async compile( options: CoreService.Compile.Options & { exportBinaries?: boolean; @@ -174,18 +193,21 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const result = responseHandler(client, req); + this.setOutputMessagesInterval(); + try { await new Promise((resolve, reject) => { result.on('data', (resp: UploadResponse) => { - this.responseService.appendToOutput({ - chunk: Buffer.from(resp.getOutStream_asU8()).toString(), - }); - this.responseService.appendToOutput({ - chunk: Buffer.from(resp.getErrStream_asU8()).toString(), - }); + this.outputString = + this.outputString + + Buffer.from(resp.getOutStream_asU8()).toString() + + Buffer.from(resp.getErrStream_asU8()).toString(); }); result.on('error', (error) => reject(error)); - result.on('end', () => resolve()); + result.on('end', () => { + this.clearOutputMessagesInterval(); + resolve(); + }); }); this.responseService.appendToOutput({ chunk: From d567109fdf04d020d99d8f00dd3f82b2fa383e0a Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 13 Jun 2022 18:52:56 +0200 Subject: [PATCH 2/5] create buffer provider --- .../src/node/core-service-impl.ts | 92 ++++++++++--------- .../src/node/output-panel-buffer-provider.ts | 28 ++++++ 2 files changed, 79 insertions(+), 41 deletions(-) create mode 100644 arduino-ide-extension/src/node/output-panel-buffer-provider.ts diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index a6b48a972..31b412873 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -25,6 +25,7 @@ import { firstToUpperCase, firstToLowerCase } from '../common/utils'; import { Port } from './cli-protocol/cc/arduino/cli/commands/v1/port_pb'; import { nls } from '@theia/core'; import { MonitorManager } from './monitor-manager'; +import { OutputPanelBufferProvider } from './output-panel-buffer-provider'; @injectable() export class CoreServiceImpl extends CoreClientAware implements CoreService { @@ -39,25 +40,8 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { protected uploading = false; - private outputString: string; - private FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS = 32; - private flushOutputMessagesInterval?: NodeJS.Timeout; - - setOutputMessagesInterval(): void { - this.flushOutputMessagesInterval = setInterval(() => { - this.responseService.appendToOutput({ - chunk: this.outputString, - }); - }, this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS); - } - - clearOutputMessagesInterval(): void { - clearInterval(this.flushOutputMessagesInterval); - this.flushOutputMessagesInterval = undefined; - } - async compile( options: CoreService.Compile.Options & { exportBinaries?: boolean; @@ -92,18 +76,25 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { this.mergeSourceOverrides(compileReq, options); const result = client.compile(compileReq); + + const compileBuffer = new OutputPanelBufferProvider( + this.flushOutputPanelMessages, + this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS + ); try { await new Promise((resolve, reject) => { result.on('data', (cr: CompileResponse) => { - this.responseService.appendToOutput({ - chunk: Buffer.from(cr.getOutStream_asU8()).toString(), - }); - this.responseService.appendToOutput({ - chunk: Buffer.from(cr.getErrStream_asU8()).toString(), - }); + compileBuffer.addChunk(cr.getOutStream_asU8()); + compileBuffer.addChunk(cr.getErrStream_asU8()); + }); + result.on('error', (error) => { + compileBuffer.clearFlushInterval(); + reject(error); + }); + result.on('end', () => { + compileBuffer.clearFlushInterval(); + resolve(); }); - result.on('error', (error) => reject(error)); - result.on('end', () => resolve()); }); this.responseService.appendToOutput({ chunk: '\n--------------------------\nCompilation complete.\n', @@ -193,19 +184,22 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const result = responseHandler(client, req); - this.setOutputMessagesInterval(); - + const uploadBuffer = new OutputPanelBufferProvider( + this.flushOutputPanelMessages, + this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS + ); try { await new Promise((resolve, reject) => { result.on('data', (resp: UploadResponse) => { - this.outputString = - this.outputString + - Buffer.from(resp.getOutStream_asU8()).toString() + - Buffer.from(resp.getErrStream_asU8()).toString(); + uploadBuffer.addChunk(resp.getOutStream_asU8()); + uploadBuffer.addChunk(resp.getErrStream_asU8()); + }); + result.on('error', (error) => { + uploadBuffer.clearFlushInterval(); + reject(error); }); - result.on('error', (error) => reject(error)); result.on('end', () => { - this.clearOutputMessagesInterval(); + uploadBuffer.clearFlushInterval(); resolve(); }); }); @@ -260,18 +254,25 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { burnReq.setVerify(options.verify); burnReq.setVerbose(options.verbose); const result = client.burnBootloader(burnReq); + + const bootloaderBuffer = new OutputPanelBufferProvider( + this.flushOutputPanelMessages, + this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS + ); try { await new Promise((resolve, reject) => { result.on('data', (resp: BurnBootloaderResponse) => { - this.responseService.appendToOutput({ - chunk: Buffer.from(resp.getOutStream_asU8()).toString(), - }); - this.responseService.appendToOutput({ - chunk: Buffer.from(resp.getErrStream_asU8()).toString(), - }); + bootloaderBuffer.addChunk(resp.getOutStream_asU8()); + bootloaderBuffer.addChunk(resp.getErrStream_asU8()); + }); + result.on('error', (error) => { + bootloaderBuffer.clearFlushInterval(); + reject(error); + }); + result.on('end', () => { + bootloaderBuffer.clearFlushInterval(); + resolve(); }); - result.on('error', (error) => reject(error)); - result.on('end', () => resolve()); }); } catch (e) { const errorMessage = nls.localize( @@ -303,4 +304,13 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { } } } + + private flushOutputPanelMessages(chunk: string): void { + this.responseService.appendToOutput({ + chunk, + }); + this.responseService.appendToOutput({ + chunk, + }); + } } diff --git a/arduino-ide-extension/src/node/output-panel-buffer-provider.ts b/arduino-ide-extension/src/node/output-panel-buffer-provider.ts new file mode 100644 index 000000000..52306c93d --- /dev/null +++ b/arduino-ide-extension/src/node/output-panel-buffer-provider.ts @@ -0,0 +1,28 @@ +export class OutputPanelBufferProvider { + chunks: Uint8Array[] = []; + + private flushInterval?: NodeJS.Timeout; + + constructor(onFlush: (chunk: string) => void, flushTimeout: number) { + this.flushInterval = setInterval(() => { + const chunkString = Buffer.concat(this.chunks).toString(); + onFlush(chunkString); + this.clearChunks(); + }, flushTimeout); + } + + public addChunk(chunk: Uint8Array): void { + this.chunks.push(chunk); + } + + private clearChunks() { + this.chunks = []; + } + + public clearFlushInterval(): void { + this.clearChunks(); + + clearInterval(this.flushInterval); + this.flushInterval = undefined; + } +} From ac7fc000432bea25f88cda3cc2b03ec6bc8ba4b9 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 13 Jun 2022 19:14:37 +0200 Subject: [PATCH 3/5] output panel buffer corrections --- arduino-ide-extension/src/node/core-service-impl.ts | 9 +++------ .../src/node/output-panel-buffer-provider.ts | 9 ++++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index 31b412873..a5f812ea0 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -78,7 +78,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const result = client.compile(compileReq); const compileBuffer = new OutputPanelBufferProvider( - this.flushOutputPanelMessages, + this.flushOutputPanelMessages.bind(this), this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); try { @@ -185,7 +185,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const result = responseHandler(client, req); const uploadBuffer = new OutputPanelBufferProvider( - this.flushOutputPanelMessages, + this.flushOutputPanelMessages.bind(this), this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); try { @@ -256,7 +256,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const result = client.burnBootloader(burnReq); const bootloaderBuffer = new OutputPanelBufferProvider( - this.flushOutputPanelMessages, + this.flushOutputPanelMessages.bind(this), this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); try { @@ -309,8 +309,5 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { this.responseService.appendToOutput({ chunk, }); - this.responseService.appendToOutput({ - chunk, - }); } } diff --git a/arduino-ide-extension/src/node/output-panel-buffer-provider.ts b/arduino-ide-extension/src/node/output-panel-buffer-provider.ts index 52306c93d..f5054a3ad 100644 --- a/arduino-ide-extension/src/node/output-panel-buffer-provider.ts +++ b/arduino-ide-extension/src/node/output-panel-buffer-provider.ts @@ -5,9 +5,12 @@ export class OutputPanelBufferProvider { constructor(onFlush: (chunk: string) => void, flushTimeout: number) { this.flushInterval = setInterval(() => { - const chunkString = Buffer.concat(this.chunks).toString(); - onFlush(chunkString); - this.clearChunks(); + if (this.chunks.length > 0) { + const chunkString = Buffer.concat(this.chunks).toString(); + this.clearChunks(); + + onFlush(chunkString); + } }, flushTimeout); } From 085f97e9989ea891c0581b822c261c3fa02179a7 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 14 Jun 2022 09:45:08 +0200 Subject: [PATCH 4/5] output buffer cleanup --- arduino-ide-extension/src/node/core-service-impl.ts | 8 ++++---- .../simple-buffer.ts} | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename arduino-ide-extension/src/node/{output-panel-buffer-provider.ts => utils/simple-buffer.ts} (94%) diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index a5f812ea0..d0ad1f890 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -25,7 +25,7 @@ import { firstToUpperCase, firstToLowerCase } from '../common/utils'; import { Port } from './cli-protocol/cc/arduino/cli/commands/v1/port_pb'; import { nls } from '@theia/core'; import { MonitorManager } from './monitor-manager'; -import { OutputPanelBufferProvider } from './output-panel-buffer-provider'; +import { SimpleBuffer } from './utils/simple-buffer'; @injectable() export class CoreServiceImpl extends CoreClientAware implements CoreService { @@ -77,7 +77,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const result = client.compile(compileReq); - const compileBuffer = new OutputPanelBufferProvider( + const compileBuffer = new SimpleBuffer( this.flushOutputPanelMessages.bind(this), this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); @@ -184,7 +184,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const result = responseHandler(client, req); - const uploadBuffer = new OutputPanelBufferProvider( + const uploadBuffer = new SimpleBuffer( this.flushOutputPanelMessages.bind(this), this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); @@ -255,7 +255,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { burnReq.setVerbose(options.verbose); const result = client.burnBootloader(burnReq); - const bootloaderBuffer = new OutputPanelBufferProvider( + const bootloaderBuffer = new SimpleBuffer( this.flushOutputPanelMessages.bind(this), this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); diff --git a/arduino-ide-extension/src/node/output-panel-buffer-provider.ts b/arduino-ide-extension/src/node/utils/simple-buffer.ts similarity index 94% rename from arduino-ide-extension/src/node/output-panel-buffer-provider.ts rename to arduino-ide-extension/src/node/utils/simple-buffer.ts index f5054a3ad..f2b700358 100644 --- a/arduino-ide-extension/src/node/output-panel-buffer-provider.ts +++ b/arduino-ide-extension/src/node/utils/simple-buffer.ts @@ -1,4 +1,4 @@ -export class OutputPanelBufferProvider { +export class SimpleBuffer { chunks: Uint8Array[] = []; private flushInterval?: NodeJS.Timeout; From 1b1610105f4e5fbe3db8caf26538234b89386293 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 14 Jun 2022 11:49:03 +0200 Subject: [PATCH 5/5] code cleanup --- arduino-ide-extension/src/node/core-service-impl.ts | 9 ++++----- arduino-ide-extension/src/node/utils/simple-buffer.ts | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index d0ad1f890..412e64807 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -27,6 +27,7 @@ import { nls } from '@theia/core'; import { MonitorManager } from './monitor-manager'; import { SimpleBuffer } from './utils/simple-buffer'; +const FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS = 32; @injectable() export class CoreServiceImpl extends CoreClientAware implements CoreService { @inject(ResponseService) @@ -40,8 +41,6 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { protected uploading = false; - private FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS = 32; - async compile( options: CoreService.Compile.Options & { exportBinaries?: boolean; @@ -79,7 +78,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const compileBuffer = new SimpleBuffer( this.flushOutputPanelMessages.bind(this), - this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS + FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); try { await new Promise((resolve, reject) => { @@ -186,7 +185,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const uploadBuffer = new SimpleBuffer( this.flushOutputPanelMessages.bind(this), - this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS + FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); try { await new Promise((resolve, reject) => { @@ -257,7 +256,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { const bootloaderBuffer = new SimpleBuffer( this.flushOutputPanelMessages.bind(this), - this.FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS + FLUSH_OUTPUT_MESSAGES_TIMEOUT_MS ); try { await new Promise((resolve, reject) => { diff --git a/arduino-ide-extension/src/node/utils/simple-buffer.ts b/arduino-ide-extension/src/node/utils/simple-buffer.ts index f2b700358..3f5acd506 100644 --- a/arduino-ide-extension/src/node/utils/simple-buffer.ts +++ b/arduino-ide-extension/src/node/utils/simple-buffer.ts @@ -1,5 +1,5 @@ export class SimpleBuffer { - chunks: Uint8Array[] = []; + private chunks: Uint8Array[] = []; private flushInterval?: NodeJS.Timeout; @@ -18,7 +18,7 @@ export class SimpleBuffer { this.chunks.push(chunk); } - private clearChunks() { + private clearChunks(): void { this.chunks = []; }