From b29bfaaf035f516ea71b1c05273d74e014efe99d Mon Sep 17 00:00:00 2001 From: Nigel Westbury Date: Tue, 9 Mar 2021 16:29:19 +0000 Subject: [PATCH] Improve ability of downstream apps to control file watching Signed-off-by: Nigel Westbury --- .../src/node/filesystem-backend-module.ts | 27 ++++++++++++++----- .../nsfw-watcher/nsfw-filesystem-service.ts | 15 +++++++---- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/packages/filesystem/src/node/filesystem-backend-module.ts b/packages/filesystem/src/node/filesystem-backend-module.ts index f60858386add5..3aa9b7ab9f11a 100644 --- a/packages/filesystem/src/node/filesystem-backend-module.ts +++ b/packages/filesystem/src/node/filesystem-backend-module.ts @@ -19,7 +19,7 @@ import { ContainerModule, interfaces } from 'inversify'; import { ConnectionHandler, JsonRpcConnectionHandler, ILogger } from '@theia/core/lib/common'; import { FileSystemWatcherServer, FileSystemWatcherService } from '../common/filesystem-watcher-protocol'; import { FileSystemWatcherServerClient } from './filesystem-watcher-client'; -import { NsfwFileSystemWatcherService } from './nsfw-watcher/nsfw-filesystem-service'; +import { NsfwFileSystemWatcherService, NsfwFileSystemWatcherServerOptions } from './nsfw-watcher/nsfw-filesystem-service'; import { MessagingService } from '@theia/core/lib/node/messaging/messaging-service'; import { NodeFileUploadService } from './node-file-upload-service'; import { NsfwOptions } from './nsfw-watcher/nsfw-options'; @@ -36,6 +36,11 @@ import { FileSystemWatcherServiceDispatcher } from './filesystem-watcher-dispatc const SINGLE_THREADED = process.argv.indexOf('--no-cluster') !== -1; const NSFW_WATCHER_VERBOSE = process.argv.indexOf('--nsfw-watcher-verbose') !== -1; +export const NsfwFileSystemWatcherProcessOptions = Symbol('NsfwFileSystemWatcherProcessOptions'); +export interface NsfwFileSystemWatcherProcessOptions { + entryPoint: string; +} + export function bindFileSystemWatcherServer(bind: interfaces.Bind, { singleThreaded }: { singleThreaded: boolean } = { singleThreaded: SINGLE_THREADED }): void { bind(NsfwOptions).toConstantValue({}); @@ -45,27 +50,35 @@ export function bindFileSystemWatcherServer(bind: interfaces.Bind, { singleThrea bind(FileSystemWatcherServer).toService(FileSystemWatcherServerClient); if (singleThreaded) { - // Bind and run the watch server in the current process: - bind(FileSystemWatcherService).toDynamicValue(ctx => { + bind(NsfwFileSystemWatcherServerOptions).toDynamicValue(ctx => { const logger = ctx.container.get(ILogger); const nsfwOptions = ctx.container.get(NsfwOptions); - const dispatcher = ctx.container.get(FileSystemWatcherServiceDispatcher); - const server = new NsfwFileSystemWatcherService({ + return { nsfwOptions, verbose: NSFW_WATCHER_VERBOSE, info: (message, ...args) => logger.info(message, ...args), error: (message, ...args) => logger.error(message, ...args) - }); + }; + }).inSingletonScope(); + // Bind and run the watch server in the current process: + bind(FileSystemWatcherService).toDynamicValue(ctx => { + const watcherOptions = ctx.container.get(NsfwFileSystemWatcherServerOptions); + const dispatcher = ctx.container.get(FileSystemWatcherServiceDispatcher); + const server = new NsfwFileSystemWatcherService(watcherOptions); server.setClient(dispatcher); return server; }).inSingletonScope(); } else { + bind(NsfwFileSystemWatcherProcessOptions).toConstantValue({ + entryPoint: path.resolve(__dirname, 'nsfw-watcher') + }); // Run the watch server in a child process. // Bind to a proxy forwarding calls to the child process. bind(FileSystemWatcherService).toDynamicValue(ctx => { const serverName = 'nsfw-watcher'; const logger = ctx.container.get(ILogger); const nsfwOptions = ctx.container.get(NsfwOptions); + const processOptions = ctx.container.get(NsfwFileSystemWatcherProcessOptions); const ipcConnectionProvider = ctx.container.get(IPCConnectionProvider); const dispatcher = ctx.container.get(FileSystemWatcherServiceDispatcher); const proxyFactory = new JsonRpcProxyFactory(); @@ -80,7 +93,7 @@ export function bindFileSystemWatcherServer(bind: interfaces.Bind, { singleThrea } ipcConnectionProvider.listen({ serverName, - entryPoint: path.resolve(__dirname, serverName), + entryPoint: processOptions.entryPoint, errorHandler: new ConnectionErrorHandler({ serverName, logger, diff --git a/packages/filesystem/src/node/nsfw-watcher/nsfw-filesystem-service.ts b/packages/filesystem/src/node/nsfw-watcher/nsfw-filesystem-service.ts index 62fb47aa8199c..354aaff2e5b08 100644 --- a/packages/filesystem/src/node/nsfw-watcher/nsfw-filesystem-service.ts +++ b/packages/filesystem/src/node/nsfw-watcher/nsfw-filesystem-service.ts @@ -29,6 +29,7 @@ export interface NsfwWatcherOptions { ignored: IMinimatch[] } +export const NsfwFileSystemWatcherServerOptions = Symbol('NsfwFileSystemWatcherServerOptions'); export interface NsfwFileSystemWatcherServerOptions { verbose: boolean; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -422,11 +423,7 @@ export class NsfwFileSystemWatcherService implements FileSystemWatcherService { let watcher = this.watchers.get(watcherKey); if (watcher === undefined) { const fsPath = FileUri.fsPath(uri); - const watcherOptions: NsfwWatcherOptions = { - ignored: resolvedOptions.ignored - .map(pattern => new Minimatch(pattern, { dot: true })), - }; - watcher = new NsfwWatcher(clientId, fsPath, watcherOptions, this.options, this.maybeClient); + watcher = this.createWatcher(clientId, fsPath, resolvedOptions); watcher.whenDisposed.then(() => this.watchers.delete(watcherKey)); this.watchers.set(watcherKey, watcher); } else { @@ -438,6 +435,14 @@ export class NsfwFileSystemWatcherService implements FileSystemWatcherService { return watcherId; } + protected createWatcher(clientId: number, fsPath: string, resolvedOptions: WatchOptions): NsfwWatcher { + const watcherOptions: NsfwWatcherOptions = { + ignored: resolvedOptions.ignored + .map(pattern => new Minimatch(pattern, { dot: true })), + }; + return new NsfwWatcher(clientId, fsPath, watcherOptions, this.options, this.maybeClient); + } + async unwatchFileChanges(watcherId: number): Promise { const handle = this.watcherHandles.get(watcherId); if (handle === undefined) {