watcher - fix some things (#207597)

This commit is contained in:
Benjamin Pasero 2024-03-13 17:43:01 +01:00 committed by GitHub
parent 3acfc00951
commit d1a1dd2784
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 43 additions and 22 deletions

View file

@ -43,6 +43,14 @@ interface IWatchRequest {
readonly correlationId?: number;
}
export interface IWatchRequestWithCorrelation extends IWatchRequest {
readonly correlationId: number;
}
export function isWatchRequestWithCorrelation(request: IWatchRequest): request is IWatchRequestWithCorrelation {
return typeof request.correlationId === 'number';
}
export interface INonRecursiveWatchRequest extends IWatchRequest {
/**

View file

@ -5,7 +5,7 @@
import { watchFile, unwatchFile, Stats } from 'fs';
import { Disposable, DisposableMap, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { ILogMessage, IUniversalWatchRequest, IWatcher } from 'vs/platform/files/common/watcher';
import { ILogMessage, IUniversalWatchRequest, IWatchRequestWithCorrelation, IWatcher, isWatchRequestWithCorrelation } from 'vs/platform/files/common/watcher';
import { Emitter, Event } from 'vs/base/common/event';
import { FileChangeType, IFileChange } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri';
@ -21,10 +21,12 @@ export abstract class BaseWatcher extends Disposable implements IWatcher {
protected readonly _onDidWatchFail = this._register(new Emitter<IUniversalWatchRequest>());
private readonly onDidWatchFail = this._onDidWatchFail.event;
private allWatchRequests = new Set<IUniversalWatchRequest>();
private readonly suspendedWatchRequests = this._register(new DisposableMap<IUniversalWatchRequest>());
private readonly allNonCorrelatedWatchRequests = new Set<IUniversalWatchRequest>();
private readonly allCorrelatedWatchRequests = new Map<number /* correlation ID */, IWatchRequestWithCorrelation>();
protected readonly suspendedWatchRequestPollingInterval: number | undefined;
private readonly suspendedWatchRequests = this._register(new DisposableMap<number /* correlation ID */>());
protected readonly suspendedWatchRequestPollingInterval: number = 5007; // node.js default
constructor() {
super();
@ -46,17 +48,27 @@ export abstract class BaseWatcher extends Disposable implements IWatcher {
this.suspendWatchRequest(request);
}
protected isCorrelated(request: IUniversalWatchRequest): boolean {
return typeof request.correlationId === 'number';
protected isCorrelated(request: IUniversalWatchRequest): request is IWatchRequestWithCorrelation {
return isWatchRequestWithCorrelation(request);
}
async watch(requests: IUniversalWatchRequest[]): Promise<void> {
this.allWatchRequests = new Set([...requests]);
this.allCorrelatedWatchRequests.clear();
this.allNonCorrelatedWatchRequests.clear();
// Remove all suspended watch requests that are no longer watched
for (const [request] of this.suspendedWatchRequests) {
if (!this.allWatchRequests.has(request)) {
this.suspendedWatchRequests.deleteAndDispose(request);
// Figure out correlated vs. non-correlated requests
for (const request of requests) {
if (this.isCorrelated(request)) {
this.allCorrelatedWatchRequests.set(request.correlationId, request);
} else {
this.allNonCorrelatedWatchRequests.add(request);
}
}
// Remove all suspended correlated watch requests that are no longer watched
for (const [correlationId] of this.suspendedWatchRequests) {
if (!this.allCorrelatedWatchRequests.has(correlationId)) {
this.suspendedWatchRequests.deleteAndDispose(correlationId);
}
}
@ -64,29 +76,32 @@ export abstract class BaseWatcher extends Disposable implements IWatcher {
}
private updateWatchers(): Promise<void> {
return this.doWatch(Array.from(this.allWatchRequests).filter(request => !this.suspendedWatchRequests.has(request)));
return this.doWatch([
...this.allNonCorrelatedWatchRequests,
...Array.from(this.allCorrelatedWatchRequests.values()).filter(request => !this.suspendedWatchRequests.has(request.correlationId))
]);
}
private suspendWatchRequest(request: IUniversalWatchRequest): void {
if (this.suspendedWatchRequests.has(request)) {
private suspendWatchRequest(request: IWatchRequestWithCorrelation): void {
if (this.suspendedWatchRequests.has(request.correlationId)) {
return; // already suspended
}
const disposables = new DisposableStore();
this.suspendedWatchRequests.set(request, disposables);
this.suspendedWatchRequests.set(request.correlationId, disposables);
this.monitorSuspendedWatchRequest(request, disposables);
this.updateWatchers();
}
private resumeWatchRequest(request: IUniversalWatchRequest): void {
this.suspendedWatchRequests.deleteAndDispose(request);
private resumeWatchRequest(request: IWatchRequestWithCorrelation): void {
this.suspendedWatchRequests.deleteAndDispose(request.correlationId);
this.updateWatchers();
}
private monitorSuspendedWatchRequest(request: IUniversalWatchRequest, disposables: DisposableStore) {
private monitorSuspendedWatchRequest(request: IWatchRequestWithCorrelation, disposables: DisposableStore) {
const resource = URI.file(request.path);
const that = this;

View file

@ -136,9 +136,7 @@ export class NodeJSWatcher extends BaseWatcher implements INonRecursiveWatcher {
}
protected warn(message: string): void {
if (this.verboseLogging) {
this._onDidLogMessage.fire({ type: 'warn', message: this.toMessage(message) });
}
this._onDidLogMessage.fire({ type: 'warn', message: this.toMessage(message) });
}
private toMessage(message: string): string {

View file

@ -81,7 +81,7 @@ export class NodeJSFileWatcherLibrary extends Disposable {
if (error.code !== 'ENOENT') {
this.error(error);
} else {
this.trace(error);
this.trace(`ignoring a path for watching who's stat info failed to resolve: ${this.request.path} (error: ${error})`);
}
this.onDidWatchFail?.();