Add line data debouncing for background tasks

Part of #129080
This commit is contained in:
Alex Ross 2021-07-21 11:33:07 +02:00
parent ef55a57968
commit dc4744f69a
No known key found for this signature in database
GPG key ID: 89DDDBA66CBA7840

View file

@ -14,7 +14,7 @@ import { IStringDictionary, values } from 'vs/base/common/collections';
import { LinkedMap, Touch } from 'vs/base/common/map';
import Severity from 'vs/base/common/severity';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { isUNC } from 'vs/base/common/extpath';
import { IFileService } from 'vs/platform/files/common/files';
@ -765,6 +765,65 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
}
}
private setupBackgroundTaskOnLineData(terminal: ITerminalInstance, watchingProblemMatcher: WatchingProblemCollector, task: CustomTask | ContributedTask): IDisposable {
let delayer: Async.Delayer<any> | undefined = undefined;
let skipLine: boolean = (!!task.command.presentation && task.command.presentation.echo);
let lastEventTime = new Date().getTime();
let lineQueue: string[] = [];
let doneDebouncing = false;
// If "enough" time (3 seconds) has passed without more line data, start processing and stop debouncing.
let startProcessingTimeout: NodeJS.Timeout | undefined;
return terminal.onLineData((line) => {
if (skipLine) {
skipLine = false;
return;
}
const currentTime = new Date().getTime();
if (!doneDebouncing && ((currentTime - lastEventTime) < 1500)) {
if (startProcessingTimeout) {
clearTimeout(startProcessingTimeout);
}
if (lineQueue.length > 300) {
lineQueue = lineQueue.slice(100, lineQueue.length);
}
lineQueue.push(line);
startProcessingTimeout = setTimeout(() => {
if (doneDebouncing) {
return;
}
doneDebouncing = true;
for (const queuedLine of lineQueue) {
watchingProblemMatcher.processLine(queuedLine);
}
lineQueue = [];
if (startProcessingTimeout) {
clearTimeout(startProcessingTimeout);
}
}, 3000);
lastEventTime = new Date().getTime();
return;
} else if (!doneDebouncing) {
doneDebouncing = true;
if (startProcessingTimeout) {
clearTimeout(startProcessingTimeout);
}
for (const queuedLine of lineQueue) {
watchingProblemMatcher.processLine(queuedLine);
}
lineQueue = [];
}
watchingProblemMatcher.processLine(line);
if (!delayer) {
delayer = new Async.Delayer(3000);
}
delayer.trigger(() => {
watchingProblemMatcher.forceDelivery();
delayer = undefined;
});
});
}
private async executeInTerminal(task: CustomTask | ContributedTask, trigger: string, resolver: VariableResolver, workspaceFolder: IWorkspaceFolder | undefined): Promise<ITaskSummary> {
let terminal: ITerminalInstance | undefined = undefined;
let executedCommand: string | undefined = undefined;
@ -807,7 +866,6 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
}
}));
watchingProblemMatcher.aboutToStart();
let delayer: Async.Delayer<any> | undefined = undefined;
[terminal, executedCommand, error] = await this.createTerminal(task, resolver, workspaceFolder);
if (error) {
@ -828,21 +886,7 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
this.logService.error('Task terminal process never got ready');
});
this.fireTaskEvent(TaskEvent.create(TaskEventKind.Start, task, terminal.instanceId));
let skipLine: boolean = (!!task.command.presentation && task.command.presentation.echo);
const onData = terminal.onLineData((line) => {
if (skipLine) {
skipLine = false;
return;
}
watchingProblemMatcher.processLine(line);
if (!delayer) {
delayer = new Async.Delayer(3000);
}
delayer.trigger(() => {
watchingProblemMatcher.forceDelivery();
delayer = undefined;
});
});
const onData = this.setupBackgroundTaskOnLineData(terminal, watchingProblemMatcher, task);
promise = new Promise<ITaskSummary>((resolve, reject) => {
const onExit = terminal!.onExit((exitCode) => {
onData.dispose();