mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Fix #16760 - account for worker process timing out during a search
This commit is contained in:
@@ -12,7 +12,7 @@ import { IProgress } from 'vs/platform/search/common/search';
|
||||
import { FileWalker } from 'vs/workbench/services/search/node/fileSearch';
|
||||
|
||||
import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search';
|
||||
import { ISearchWorker, ISearchWorkerConfig } from './worker/searchWorkerIpc';
|
||||
import { ISearchWorker } from './worker/searchWorkerIpc';
|
||||
import { ITextSearchWorkerProvider } from './textSearchWorkerProvider';
|
||||
|
||||
export class Engine implements ISearchEngine<ISerializedFileMatch> {
|
||||
@@ -55,8 +55,7 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
|
||||
|
||||
initializeWorkers(): void {
|
||||
this.workers.forEach(w => {
|
||||
const config: ISearchWorkerConfig = { pattern: this.config.contentPattern, fileEncoding: this.config.fileEncoding };
|
||||
w.initialize(config)
|
||||
w.initialize()
|
||||
.then(null, onUnexpectedError);
|
||||
});
|
||||
}
|
||||
@@ -94,7 +93,8 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
|
||||
this.nextWorker = (this.nextWorker + 1) % this.workers.length;
|
||||
|
||||
const maxResults = this.config.maxResults && (this.config.maxResults - this.numResults);
|
||||
worker.search({ absolutePaths: batch, maxResults }).then(result => {
|
||||
const searchArgs = { absolutePaths: batch, maxResults, pattern: this.config.contentPattern, fileEncoding: this.config.fileEncoding };
|
||||
worker.search(searchArgs).then(result => {
|
||||
if (!result || this.limitReached || this.isCanceled) {
|
||||
return unwind(batchBytes);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ILineMatch } from 'vs/platform/search/common/search';
|
||||
import { UTF16le, UTF16be, UTF8, UTF8_with_bom, encodingExists, decode } from 'vs/base/node/encoding';
|
||||
import { detectMimeAndEncodingFromBuffer } from 'vs/base/node/mime';
|
||||
|
||||
import { ISearchWorker, ISearchWorkerConfig, ISearchWorkerSearchArgs, ISearchWorkerSearchResult } from './searchWorkerIpc';
|
||||
import { ISearchWorker, ISearchWorkerSearchArgs, ISearchWorkerSearchResult } from './searchWorkerIpc';
|
||||
|
||||
interface ReadLinesOptions {
|
||||
bufferLength: number;
|
||||
@@ -36,20 +36,24 @@ function onError(error: any): void {
|
||||
export class SearchWorkerManager implements ISearchWorker {
|
||||
private currentSearchEngine: SearchWorkerEngine;
|
||||
|
||||
initialize(config: ISearchWorkerConfig): TPromise<void> {
|
||||
this.currentSearchEngine = new SearchWorkerEngine(config);
|
||||
initialize(): TPromise<void> {
|
||||
this.currentSearchEngine = new SearchWorkerEngine();
|
||||
return TPromise.wrap<void>(undefined);
|
||||
}
|
||||
|
||||
cancel(): TPromise<void> {
|
||||
// Cancel the current search. It will stop searching and close its open files.
|
||||
this.currentSearchEngine.cancel();
|
||||
if (this.currentSearchEngine) {
|
||||
this.currentSearchEngine.cancel();
|
||||
}
|
||||
|
||||
return TPromise.wrap<void>(null);
|
||||
}
|
||||
|
||||
search(args: ISearchWorkerSearchArgs): TPromise<ISearchWorkerSearchResult> {
|
||||
if (!this.currentSearchEngine) {
|
||||
return TPromise.wrapError(new Error('SearchWorker is not initialized'));
|
||||
// Worker timed out during search
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
return this.currentSearchEngine.searchBatch(args);
|
||||
@@ -63,27 +67,21 @@ interface IFileSearchResult {
|
||||
}
|
||||
|
||||
export class SearchWorkerEngine {
|
||||
private contentPattern: RegExp;
|
||||
private fileEncoding: string;
|
||||
private nextSearch = TPromise.wrap(null);
|
||||
|
||||
private isCanceled = false;
|
||||
|
||||
constructor(config: ISearchWorkerConfig) {
|
||||
this.contentPattern = strings.createRegExp(config.pattern.pattern, config.pattern.isRegExp, { matchCase: config.pattern.isCaseSensitive, wholeWord: config.pattern.isWordMatch, multiline: false, global: true });
|
||||
this.fileEncoding = encodingExists(config.fileEncoding) ? config.fileEncoding : UTF8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches some number of the given paths concurrently, and starts searches in other paths when those complete.
|
||||
*/
|
||||
searchBatch(args: ISearchWorkerSearchArgs): TPromise<ISearchWorkerSearchResult> {
|
||||
const contentPattern = strings.createRegExp(args.pattern.pattern, args.pattern.isRegExp, { matchCase: args.pattern.isCaseSensitive, wholeWord: args.pattern.isWordMatch, multiline: false, global: true });
|
||||
const fileEncoding = encodingExists(args.fileEncoding) ? args.fileEncoding : UTF8;
|
||||
return this.nextSearch =
|
||||
this.nextSearch.then(() => this._searchBatch(args));
|
||||
this.nextSearch.then(() => this._searchBatch(args, contentPattern, fileEncoding));
|
||||
}
|
||||
|
||||
|
||||
private _searchBatch(args: ISearchWorkerSearchArgs): TPromise<ISearchWorkerSearchResult> {
|
||||
private _searchBatch(args: ISearchWorkerSearchArgs, contentPattern: RegExp, fileEncoding: string): TPromise<ISearchWorkerSearchResult> {
|
||||
if (this.isCanceled) {
|
||||
return TPromise.wrap(null);
|
||||
}
|
||||
@@ -97,7 +95,7 @@ export class SearchWorkerEngine {
|
||||
|
||||
// Search in the given path, and when it's finished, search in the next path in absolutePaths
|
||||
const startSearchInFile = (absolutePath: string): TPromise<void> => {
|
||||
return this.searchInFile(absolutePath, this.contentPattern, this.fileEncoding, args.maxResults && (args.maxResults - result.numMatches)).then(fileResult => {
|
||||
return this.searchInFile(absolutePath, contentPattern, fileEncoding, args.maxResults && (args.maxResults - result.numMatches)).then(fileResult => {
|
||||
// Finish early if search is canceled
|
||||
if (this.isCanceled) {
|
||||
return;
|
||||
|
||||
@@ -11,12 +11,9 @@ import { ISerializedFileMatch } from '../search';
|
||||
import { IPatternInfo } from 'vs/platform/search/common/search';
|
||||
import { SearchWorkerManager } from './searchWorker';
|
||||
|
||||
export interface ISearchWorkerConfig {
|
||||
export interface ISearchWorkerSearchArgs {
|
||||
pattern: IPatternInfo;
|
||||
fileEncoding: string;
|
||||
}
|
||||
|
||||
export interface ISearchWorkerSearchArgs {
|
||||
absolutePaths: string[];
|
||||
maxResults?: number;
|
||||
}
|
||||
@@ -28,13 +25,13 @@ export interface ISearchWorkerSearchResult {
|
||||
}
|
||||
|
||||
export interface ISearchWorker {
|
||||
initialize(config: ISearchWorkerConfig): TPromise<void>;
|
||||
initialize(): TPromise<void>;
|
||||
search(args: ISearchWorkerSearchArgs): TPromise<ISearchWorkerSearchResult>;
|
||||
cancel(): TPromise<void>;
|
||||
}
|
||||
|
||||
export interface ISearchWorkerChannel extends IChannel {
|
||||
call(command: 'initialize', config: ISearchWorkerConfig): TPromise<void>;
|
||||
call(command: 'initialize'): TPromise<void>;
|
||||
call(command: 'search', args: ISearchWorkerSearchArgs): TPromise<ISearchWorkerSearchResult>;
|
||||
call(command: 'cancel'): TPromise<void>;
|
||||
call(command: string, arg?: any): TPromise<any>;
|
||||
@@ -46,7 +43,7 @@ export class SearchWorkerChannel implements ISearchWorkerChannel {
|
||||
|
||||
call(command: string, arg?: any): TPromise<any> {
|
||||
switch (command) {
|
||||
case 'initialize': return this.worker.initialize(arg);
|
||||
case 'initialize': return this.worker.initialize();
|
||||
case 'search': return this.worker.search(arg);
|
||||
case 'cancel': return this.worker.cancel();
|
||||
}
|
||||
@@ -56,8 +53,8 @@ export class SearchWorkerChannel implements ISearchWorkerChannel {
|
||||
export class SearchWorkerChannelClient implements ISearchWorker {
|
||||
constructor(private channel: ISearchWorkerChannel) { }
|
||||
|
||||
initialize(config: ISearchWorkerConfig): TPromise<void> {
|
||||
return this.channel.call('initialize', config);
|
||||
initialize(): TPromise<void> {
|
||||
return this.channel.call('initialize');
|
||||
}
|
||||
|
||||
search(args: ISearchWorkerSearchArgs): TPromise<ISearchWorkerSearchResult> {
|
||||
|
||||
Reference in New Issue
Block a user