import * as monaco from 'monaco-editor' import type { LanguageServiceDefaults } from '../register' import type { LogWorker, ICreateData } from './logWorker' import { LOG_LANGUAGE_ID } from '../definitions' const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000 // 2min export class WorkerManager { private readonly _defaults: LanguageServiceDefaults private _worker: monaco.editor.MonacoWebWorker | null = null private _client: Promise | null private readonly _idleCheckInterval: number private _lastUsedTime: number constructor(defaults: LanguageServiceDefaults) { this._defaults = defaults this._worker = null this._client = null this._idleCheckInterval = window.setInterval(() => this._checkIfIdle(), 30 * 1000) this._lastUsedTime = 0 } private _stopWorker(): void { if (this._worker) { this._worker.dispose() this._worker = null } this._client = null } dispose(): void { clearInterval(this._idleCheckInterval) this._stopWorker() } private _checkIfIdle(): void { if (!this._worker) { return } let timePassedSinceLastUsed = Date.now() - this._lastUsedTime if (timePassedSinceLastUsed > STOP_WHEN_IDLE_FOR) { this._stopWorker() } } private _getClient(): Promise { this._lastUsedTime = Date.now() if (!this._client) { this._worker = monaco.createWebWorker({ // module that exports the create() method and returns a `LogWorker` instance moduleId: 'vs/language/log/logWorker', createWorker: () => { return new Worker(new URL('./log.worker?esm', import.meta.url), { type: 'module' }) }, label: LOG_LANGUAGE_ID, // passed in to the create() method createData: { languageId: LOG_LANGUAGE_ID, } satisfies ICreateData, }) this._client = >(this._worker.getProxy()) } return this._client } getLanguageServiceWorker(...resources: monaco.Uri[]): Promise { let _client: LogWorker return this._getClient() .then((client) => { _client = client }) .then((_) => { if (this._worker) { return this._worker.withSyncedResources(resources) } }) .then((_) => _client) } }