Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { LabelService, RecentFilesManager, useInjectable } from '@opensumi/ide-c
import { Icon, getIcon } from '@opensumi/ide-core-browser/lib/components';
import { ChatFeatureRegistryToken, URI, localize } from '@opensumi/ide-core-common';
import { CommandService } from '@opensumi/ide-core-common/lib/command';
import { defaultFilesWatcherExcludes } from '@opensumi/ide-core-common/lib/preferences/file-watch';
import { WorkbenchEditorService } from '@opensumi/ide-editor';
import { FileSearchServicePath, IFileSearchService } from '@opensumi/ide-file-search';
import { IMessageService } from '@opensumi/ide-overlay';
Expand Down Expand Up @@ -216,7 +217,7 @@ export const ChatMentionInput = (props: IChatMentionInputProps) => {
useGitIgnore: true,
noIgnoreParent: true,
fuzzyMatch: true,
excludePatterns: ['**/node_modules/**/*', '**/.git/**/*'],
excludePatterns: Object.keys(defaultFilesWatcherExcludes),
limit: 10,
});
const folders = Array.from(
Expand Down
4 changes: 2 additions & 2 deletions packages/ai-native/src/browser/mcp/tools/fileSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { z } from 'zod';
import { Autowired } from '@opensumi/di';
import { getValidateInput } from '@opensumi/ide-addons/lib/browser/file-search.contribution';
import { Domain, URI } from '@opensumi/ide-core-common';
import { defaultFilesWatcherExcludes } from '@opensumi/ide-core-common/lib/preferences/file-watch';
import { FileSearchServicePath, IFileSearchService } from '@opensumi/ide-file-search/lib/common';
import { IWorkspaceService } from '@opensumi/ide-workspace';

Expand Down Expand Up @@ -63,8 +64,7 @@ export class FileSearchTool implements MCPServerContribution {
const searchPattern = this.normalizeQuery(args.query);
const searchResults = await this.fileSearchService.find(searchPattern, {
rootUris: [new URI(workspaceRoots[0].uri).codeUri.fsPath],
// TODO: 忽略配置
excludePatterns: ['**/node_modules/**'],
excludePatterns: Object.keys(defaultFilesWatcherExcludes),
limit: 100,
useGitIgnore: true,
noIgnoreParent: true,
Expand Down
46 changes: 35 additions & 11 deletions packages/file-service/src/browser/file-service-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
parseGlob,
} from '@opensumi/ide-core-browser';
import { CorePreferences } from '@opensumi/ide-core-browser/lib/core-preferences';
import { FileSystemProviderCapabilities, IEventBus, Schemes, isUndefined } from '@opensumi/ide-core-common';
import { FileSystemProviderCapabilities, IEventBus, ILogger, Schemes, isUndefined } from '@opensumi/ide-core-common';
import { IElectronMainUIService } from '@opensumi/ide-core-common/lib/electron';
import { IApplicationService } from '@opensumi/ide-core-common/lib/types/application';
import { Iterable } from '@opensumi/monaco-editor-core/esm/vs/base/common/iterator';
Expand Down Expand Up @@ -116,6 +116,8 @@ export class FileServiceClient implements IFileServiceClient, IDisposable {
@Autowired(IApplicationService)
protected readonly applicationService: IApplicationService;

@Autowired(ILogger)
private readonly logger: ILogger;
private get clientId() {
return this.applicationService.clientId;
}
Expand Down Expand Up @@ -358,20 +360,23 @@ export class FileServiceClient implements IFileServiceClient, IDisposable {
const pollingWatch = pollingWatcherDirectories.some((dir) => uri.path.toString().startsWith(dir));

const _uri = this.convertUri(uri.toString());
const originWatcher = this.uriWatcherMap.get(_uri.toString());
if (originWatcher) {
// 这里兼容重连逻辑,重连时 watcher 会 disposed,需要重新生成
if (!originWatcher.isDisposed()) {
return originWatcher;
} else {
this.uriWatcherMap.delete(_uri.toString());
}
}

const id = this.watcherId++;
let id = 0;
const provider = await this.getProvider(_uri.scheme);
const schemaWatchIdList = this.watcherWithSchemaMap.get(_uri.scheme) || [];

let prevWatcher: IFileServiceWatcher | undefined;
if (this.uriWatcherMap.has(_uri.toString())) {
prevWatcher = this.uriWatcherMap.get(_uri.toString()) as IFileServiceWatcher;
prevWatcher.dispose();
}

if (prevWatcher) {
id = prevWatcher.watchId;
} else {
id = this.watcherId++;
}

Comment thread
erha19 marked this conversation as resolved.
const watcherId = await provider.watch(_uri.codeUri, {
excludes,
pollingWatch,
Expand Down Expand Up @@ -710,4 +715,23 @@ export class FileServiceClient implements IFileServiceClient, IDisposable {
protected async doGetMoveToTrash(option?: { moveToTrash?: boolean }): Promise<boolean> {
return option && typeof option.moveToTrash !== 'undefined' ? option.moveToTrash : this.options.moveToTrash;
}

async reconnect() {
const provider = await this.getProvider(Schemes.file);
if (provider.initialize) {
await provider.initialize(this.clientId, this.appConfig.recursiveWatcherBackend);
}
const uriList = Array.from(this.uriWatcherMap.keys());
for (const uriString of uriList) {
try {
const uri = new URI(uriString);
const watcher = this.uriWatcherMap.get(uriString);
if (watcher) {
await this.watchFileChanges(uri);
}
} catch (err) {
this.logger?.error('Error reconnecting watcher for:', uriString, err);
}
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
11 changes: 11 additions & 0 deletions packages/file-service/src/browser/file-service-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Domain,
FsProviderContribution,
IDisposable,
ILogger,
Schemes,
} from '@opensumi/ide-core-browser';

Expand All @@ -27,6 +28,12 @@ export class FileServiceContribution implements ClientAppContribution, IDisposab
@Autowired(FsProviderContribution)
contributionProvider: ContributionProvider<FsProviderContribution>;

@Autowired(IFileServiceClient)
protected readonly fileServiceClient: IFileServiceClient;

@Autowired(ILogger)
protected readonly logger: ILogger;

constructor() {
// 初始化资源读取逻辑,需要在最早初始化时注册
// 否则后续注册的 debug\user_stroage 等将无法正常使用
Expand All @@ -53,6 +60,10 @@ export class FileServiceContribution implements ClientAppContribution, IDisposab
}
}

onReconnect() {
this.fileServiceClient.reconnect().catch((err) => this.logger.error('Failed to reconnect watchers:', err));
}

dispose() {
this._disposables.dispose();
}
Expand Down
4 changes: 4 additions & 0 deletions packages/file-service/src/common/file-service-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export interface IFileServiceClient {

unwatchFileChanges(watchId: number): Promise<void>;

reconnect(): Promise<void>;

dispose(): void;

setWatchFileExcludes(excludes: string[]): Promise<void>;

getWatchFileExcludes(): Promise<string[]>;
Expand Down
8 changes: 8 additions & 0 deletions packages/file-service/src/node/watcher-process-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,18 @@ export class WatcherProcessManagerImpl implements IWatcherProcessManager {
}

async createProcess(clientId: string, backend?: RecursiveWatcherBackend) {
this._whenReadyDeferred = new Deferred();
this.logger.log('create watcher process for client: ', clientId);
this.logger.log('appconfig watcherHost: ', this.watcherHost);

const ipcHandlerPath = await this.getIPCHandlerPath('watcher_process');
// 如果存在连接,则关闭连接, 避免重复创建
const server = this.clientWatcherConnectionServer.get(clientId);
if (server) {
// 等待真正关闭后再移除引用,避免句柄和端口泄漏
await new Promise<void>((res) => server.close(() => res()));
this.clientWatcherConnectionServer.delete(clientId);
}
await this.createWatcherServer(clientId, ipcHandlerPath);
Comment thread
erha19 marked this conversation as resolved.

const pid = await this.createWatcherProcess(clientId, ipcHandlerPath, backend);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,6 @@ describe('FileTreeContribution', () => {
expect(title).toBe('userhome');
});

it('should onReconnect be work', async () => {
const contribution = mockInjector.get(FileTreeContribution);
contribution.onReconnect();
expect(mockFileTreeService.reWatch).toHaveBeenCalledTimes(1);
});

it('should registerCommands be work', async () => {
const contribution = mockInjector.get(FileTreeContribution);
const register = jest.fn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,15 +225,6 @@ describe('FileTree Service should be work alone', () => {
await fileTreeService.flushEventQueue();
});

it('Re-watch should be work while re-connect', async () => {
const fileTreeContribution = injector.get(FileTreeContribution);
const testUri = new URI('file://userhome/test.js');
fileTreeService.startWatchFileEvent();
await fileTreeService.watchFilesChange(testUri);
await fileTreeContribution.onReconnect();
expect(fileChangeWatcher.onFilesChanged).toHaveBeenCalledTimes(2);
});

it('Commands should be work', () => {
const testUri = new URI('file://userhome/test.js');
// openAndFixedFile
Expand Down
4 changes: 0 additions & 4 deletions packages/file-tree-next/src/browser/file-tree-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,6 @@ export class FileTreeContribution
return resourceTitle;
}

onReconnect() {
this.fileTreeService.reWatch();
}

private revealFile(locationUri: URI) {
if (locationUri) {
if (this.isRendered) {
Expand Down
8 changes: 0 additions & 8 deletions packages/file-tree-next/src/browser/file-tree.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,14 +680,6 @@ export class FileTreeService extends Tree implements IFileTreeService {
}
}

public reWatch() {
// 重连时重新监听文件变化
for (const [uri, watcher] of this._fileServiceWatchers) {
watcher.dispose();
this.watchFilesChange(new URI(uri));
}
}

get isMultipleWorkspace(): boolean {
return !!this.workspaceService.workspace && !this.workspaceService.workspace.isDirectory;
}
Expand Down
Loading