diff --git a/packages/backend/src/managers/catalogManager.ts b/packages/backend/src/managers/catalogManager.ts index 7043ebdef..cbbd3fc62 100644 --- a/packages/backend/src/managers/catalogManager.ts +++ b/packages/backend/src/managers/catalogManager.ts @@ -24,10 +24,10 @@ import type { Category } from '@shared/src/models/ICategory'; import type { Recipe } from '@shared/src/models/IRecipe'; import type { ModelInfo } from '@shared/src/models/IModelInfo'; import { MSG_NEW_CATALOG_STATE } from '@shared/Messages'; -import { fs } from '@podman-desktop/api'; -import type { Webview } from '@podman-desktop/api'; +import { type Disposable, type Webview, fs } from '@podman-desktop/api'; -export class CatalogManager { +export class CatalogManager implements Disposable { + private watchers: Map = new Map(); private catalog: Catalog; constructor( @@ -42,6 +42,10 @@ export class CatalogManager { }; } + dispose(): void { + Array.from(this.watchers.values()).forEach(watcher => watcher.dispose()); + } + public getCatalog(): Catalog { return this.catalog; } @@ -98,7 +102,11 @@ export class CatalogManager { } watchCatalogFile(path: string) { + if (this.watchers.has(path)) throw new Error(`A watcher already exist for file ${path}.`); + const watcher = fs.createFileSystemWatcher(path); + this.watchers.set(path, watcher); + watcher.onDidCreate(async () => { try { const cat = await this.readAndAnalyzeCatalog(path); diff --git a/packages/backend/src/managers/modelsManager.ts b/packages/backend/src/managers/modelsManager.ts index a5cd7274c..12163cbdd 100644 --- a/packages/backend/src/managers/modelsManager.ts +++ b/packages/backend/src/managers/modelsManager.ts @@ -19,7 +19,7 @@ import type { LocalModelInfo } from '@shared/src/models/ILocalModelInfo'; import fs from 'fs'; import * as path from 'node:path'; -import { type Webview, fs as apiFs } from '@podman-desktop/api'; +import { type Webview, fs as apiFs, type Disposable } from '@podman-desktop/api'; import { MSG_NEW_MODELS_STATE } from '@shared/Messages'; import type { CatalogManager } from './catalogManager'; import type { ModelInfo } from '@shared/src/models/IModelInfo'; @@ -40,7 +40,7 @@ interface DownloadModelFailureResult { error: string; } -export class ModelsManager { +export class ModelsManager implements Disposable { #modelsDir: string; #models: Map; #watcher?: podmanDesktopApi.FileSystemWatcher; @@ -56,6 +56,11 @@ export class ModelsManager { this.#models = new Map(); } + dispose(): void { + this.#models.clear(); + this.#watcher.dispose(); + } + async loadLocalModels() { this.catalogManager.getModels().forEach(m => this.#models.set(m.id, m)); const reloadLocalModels = async () => { diff --git a/packages/backend/src/managers/podmanConnection.ts b/packages/backend/src/managers/podmanConnection.ts index c42bfc2ea..09a8d6b42 100644 --- a/packages/backend/src/managers/podmanConnection.ts +++ b/packages/backend/src/managers/podmanConnection.ts @@ -22,6 +22,7 @@ import { type UpdateContainerConnectionEvent, containerEngine, type PodInfo, + type Disposable, } from '@podman-desktop/api'; export type startupHandle = () => void; @@ -31,7 +32,7 @@ export type podStartHandle = (pod: PodInfo) => void; export type podStopHandle = (pod: PodInfo) => void; export type podRemoveHandle = (podId: string) => void; -export class PodmanConnection { +export class PodmanConnection implements Disposable { #firstFound = false; #toExecuteAtStartup: startupHandle[] = []; #toExecuteAtMachineStop: machineStopHandle[] = []; @@ -40,12 +41,18 @@ export class PodmanConnection { #toExecuteAtPodStop: podStopHandle[] = []; #toExecuteAtPodRemove: podRemoveHandle[] = []; + #onEventDisposable: Disposable | undefined; + init(): void { this.listenRegistration(); this.listenMachine(); this.watchPods(); } + dispose(): void { + this.#onEventDisposable?.dispose(); + } + listenRegistration() { // In case the extension has not yet registered, we listen for new registrations // and retain the first started podman provider @@ -111,7 +118,9 @@ export class PodmanConnection { } watchPods() { - containerEngine.onEvent(event => { + if (this.#onEventDisposable !== undefined) throw new Error('already watching pods.'); + + this.#onEventDisposable = containerEngine.onEvent(event => { if (event.Type !== 'pod') { return; } diff --git a/packages/backend/src/studio.ts b/packages/backend/src/studio.ts index c48e39f75..93c4448d7 100644 --- a/packages/backend/src/studio.ts +++ b/packages/backend/src/studio.ts @@ -16,6 +16,7 @@ * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ +import { Uri, window, env } from '@podman-desktop/api'; import type { ExtensionContext, TelemetryLogger, @@ -23,7 +24,6 @@ import type { WebviewPanel, WebviewPanelOnDidChangeViewStateEvent, } from '@podman-desktop/api'; -import { Uri, window, env } from '@podman-desktop/api'; import { RpcExtension } from '@shared/src/messages/MessageProxy'; import { StudioApiImpl } from './studio-api-impl'; import { ApplicationManager } from './managers/applicationManager'; @@ -167,6 +167,9 @@ export class Studio { // Register the instance this.rpcExtension.registerInstance(StudioApiImpl, this.studioApi); + this.#extensionContext.subscriptions.push(this.catalogManager); + this.#extensionContext.subscriptions.push(this.modelsManager); + this.#extensionContext.subscriptions.push(podmanConnection); } public async deactivate(): Promise {