Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: managerクラスの取得方法を変更 #2339

Merged
merged 9 commits into from
Nov 5, 2024
91 changes: 52 additions & 39 deletions src/backend/electron/engineAndVvppController.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import log from "electron-log/main";
import { BrowserWindow, dialog } from "electron";

import EngineInfoManager from "./manager/engineInfoManager";
import EngineProcessManager from "./manager/engineProcessManager";
import VvppManager from "./manager/vvppManager";
import { RuntimeInfoManager } from "./manager/RuntimeInfoManager";
import { ElectronConfigManager } from "./electronConfig";
import { getConfigManager } from "./electronConfig";
import { getEngineInfoManager } from "./manager/engineInfoManager";
import { getEngineProcessManager } from "./manager/engineProcessManager";
import { getRuntimeInfoManager } from "./manager/RuntimeInfoManager";
import { getVvppManager } from "./manager/vvppManager";
import {
EngineId,
EngineInfo,
Expand All @@ -17,20 +17,13 @@ import {
* エンジンとVVPP周りの処理の流れを制御するクラス。
*/
export class EngineAndVvppController {
constructor(
private runtimeInfoManager: RuntimeInfoManager,
private configManager: ElectronConfigManager,
private engineInfoManager: EngineInfoManager,
private engineProcessManager: EngineProcessManager,
private vvppManager: VvppManager,
) {}

/**
Hiroshiba marked this conversation as resolved.
Show resolved Hide resolved
* VVPPエンジンをインストールする。
*/
async installVvppEngine(vvppPath: string) {
const vvppManager = getVvppManager();
try {
await this.vvppManager.install(vvppPath);
await vvppManager.install(vvppPath);
return true;
} catch (e) {
dialog.showErrorBox(
Expand Down Expand Up @@ -96,21 +89,23 @@ export class EngineAndVvppController {
*/
async uninstallVvppEngine(engineId: EngineId) {
let engineInfo: EngineInfo | undefined = undefined;
const engineInfoManager = getEngineInfoManager();
const vvppManager = getVvppManager();
try {
engineInfo = this.engineInfoManager.fetchEngineInfo(engineId);
engineInfo = engineInfoManager.fetchEngineInfo(engineId);
if (!engineInfo) {
throw new Error(
`No such engineInfo registered: engineId == ${engineId}`,
);
}

if (!this.vvppManager.canUninstall(engineInfo)) {
if (!vvppManager.canUninstall(engineInfo)) {
throw new Error(`Cannot uninstall: engineId == ${engineId}`);
}

// Windows環境だとエンジンを終了してから削除する必要がある。
// そのため、アプリの終了時に削除するようにする。
this.vvppManager.markWillDelete(engineId);
vvppManager.markWillDelete(engineId);
return true;
} catch (e) {
const engineName = engineInfo?.name ?? engineId;
Expand All @@ -125,49 +120,57 @@ export class EngineAndVvppController {

/** エンジンの設定を更新し、保存する */
updateEngineSetting(engineId: EngineId, engineSetting: EngineSettingType) {
const engineSettings = this.configManager.get("engineSettings");
const configManager = getConfigManager();
const engineSettings = configManager.get("engineSettings");
engineSettings[engineId] = engineSetting;
this.configManager.set(`engineSettings`, engineSettings);
configManager.set(`engineSettings`, engineSettings);
}

// エンジンの準備と起動
async launchEngines() {
// AltPortInfosを再生成する。
this.engineInfoManager.initializeAltPortInfo();
const engineInfoManager = getEngineInfoManager();
engineInfoManager.initializeAltPortInfo();

// TODO: デフォルトエンジンの処理をConfigManagerに移してブラウザ版と共通化する
const engineInfos = this.engineInfoManager.fetchEngineInfos();
const engineSettings = this.configManager.get("engineSettings");
const engineInfos = engineInfoManager.fetchEngineInfos();
const configManager = getConfigManager();
const engineSettings = configManager.get("engineSettings");
for (const engineInfo of engineInfos) {
if (!engineSettings[engineInfo.uuid]) {
// 空オブジェクトをパースさせることで、デフォルト値を取得する
engineSettings[engineInfo.uuid] = engineSettingSchema.parse({});
}
}
this.configManager.set("engineSettings", engineSettings);
configManager.set("engineSettings", engineSettings);

await this.engineProcessManager.runEngineAll();
this.runtimeInfoManager.setEngineInfos(
const engineProcessManager = getEngineProcessManager();
await engineProcessManager.runEngineAll();
const runtimeInfoManager = getRuntimeInfoManager();
runtimeInfoManager.setEngineInfos(
engineInfos,
this.engineInfoManager.altPortInfos,
engineInfoManager.altPortInfos,
);
await this.runtimeInfoManager.exportFile();
await runtimeInfoManager.exportFile();
}

/**
* エンジンを再起動する。
* エンジンの起動が開始したらresolve、起動が失敗したらreject。
*/
async restartEngines(engineId: EngineId) {
await this.engineProcessManager.restartEngine(engineId);
const engineProcessManager = getEngineProcessManager();
await engineProcessManager.restartEngine(engineId);

// ランタイム情報の更新
// TODO: setからexportの処理は排他処理にしたほうがより良い
this.runtimeInfoManager.setEngineInfos(
this.engineInfoManager.fetchEngineInfos(),
this.engineInfoManager.altPortInfos,
const runtimeInfoManager = getRuntimeInfoManager();
const engineInfoManager = getEngineInfoManager();
runtimeInfoManager.setEngineInfos(
engineInfoManager.fetchEngineInfos(),
engineInfoManager.altPortInfos,
);
await this.runtimeInfoManager.exportFile();
await runtimeInfoManager.exportFile();
}

/**
Expand All @@ -176,16 +179,15 @@ export class EngineAndVvppController {
* そうでない場合は Promise を返す。
*/
cleanupEngines(): Promise<void> | "alreadyCompleted" {
const killingProcessPromises = this.engineProcessManager.killEngineAll();
const engineProcessManager = getEngineProcessManager();
const killingProcessPromises = engineProcessManager.killEngineAll();
const numLivingEngineProcess = Object.entries(
killingProcessPromises,
).length;

// 前処理が完了している場合
if (
numLivingEngineProcess === 0 &&
!this.vvppManager.hasMarkedEngineDirs()
) {
const vvppManager = getVvppManager();
if (numLivingEngineProcess === 0 && !vvppManager.hasMarkedEngineDirs()) {
return "alreadyCompleted";
}

Expand Down Expand Up @@ -217,7 +219,8 @@ export class EngineAndVvppController {
log.info(
"All ENGINE process kill operations done. Running post engine kill process",
);
return this.vvppManager.handleMarkedEngineDirs();
const vvppManager = getVvppManager();
return vvppManager.handleMarkedEngineDirs();
Hiroshiba marked this conversation as resolved.
Show resolved Hide resolved
});
}

Expand All @@ -228,7 +231,17 @@ export class EngineAndVvppController {
*/
gracefulShutdown() {
const engineCleanupResult = this.cleanupEngines();
const configSavedResult = this.configManager.ensureSaved();
const configManager = getConfigManager();
const configSavedResult = configManager.ensureSaved();
return { engineCleanupResult, configSavedResult };
}
}

let manager: EngineAndVvppController | undefined;

export const getEngineAndVvppController = () => {
if (manager == undefined) {
manager = new EngineAndVvppController();
}
return manager;
};
53 changes: 25 additions & 28 deletions src/backend/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ import log from "electron-log/main";
import dayjs from "dayjs";
import windowStateKeeper from "electron-window-state";
import { hasSupportedGpu } from "./device";
import EngineInfoManager from "./manager/engineInfoManager";
import EngineProcessManager from "./manager/engineProcessManager";
import VvppManager, { isVvppFile } from "./manager/vvppManager";
import {
getEngineInfoManager,
initializeEngineInfoManager,
} from "./manager/engineInfoManager";
import {
getEngineProcessManager,
initializeEngineProcessManager,
} from "./manager/engineProcessManager";
import { initializeVvppManager, isVvppFile } from "./manager/vvppManager";
import configMigration014 from "./configMigration014";
import { RuntimeInfoManager } from "./manager/RuntimeInfoManager";
import { initializeRuntimeInfoManager } from "./manager/RuntimeInfoManager";
import { registerIpcMainHandle, ipcMainSendProxy, IpcMainHandle } from "./ipc";
import { getConfigManager } from "./electronConfig";
import { EngineAndVvppController } from "./engineAndVvppController";
import { getEngineAndVvppController } from "./engineAndVvppController";
import { writeFileSafely } from "./fileHelper";
import { failure, success } from "@/type/result";
import { AssetTextFileNames } from "@/type/staticResources";
Expand Down Expand Up @@ -170,35 +176,25 @@ const onEngineProcessError = (engineInfo: EngineInfo, error: Error) => {
dialog.showErrorBox("音声合成エンジンエラー", error.message);
};

const runtimeInfoManager = new RuntimeInfoManager(
initializeRuntimeInfoManager(
path.join(app.getPath("userData"), "runtime-info.json"),
app.getVersion(),
);

const configManager = getConfigManager();

const engineInfoManager = new EngineInfoManager({
configManager,
initializeEngineInfoManager({
defaultEngineDir: appDirPath,
vvppEngineDir,
});
const engineProcessManager = new EngineProcessManager({
configManager,
onEngineProcessError,
engineInfosFetcher:
engineInfoManager.fetchEngineInfos.bind(engineInfoManager),
engineAltPortUpdater: engineInfoManager.updateAltPort.bind(engineInfoManager),
engineSettingsGetter: () => configManager.get("engineSettings"),
});
const vvppManager = new VvppManager({ vvppEngineDir });

const engineAndVvppController = new EngineAndVvppController(
runtimeInfoManager,
configManager,
engineInfoManager,
engineProcessManager,
vvppManager,
);

initializeEngineProcessManager({ onEngineProcessError });

initializeVvppManager({ vvppEngineDir });

const configManager = getConfigManager();

const engineInfoManager = getEngineInfoManager();

const engineAndVvppController = getEngineAndVvppController();
Hiroshiba marked this conversation as resolved.
Show resolved Hide resolved

// エンジンのフォルダを開く
function openEngineDirectory(engineId: EngineId) {
Expand Down Expand Up @@ -649,7 +645,8 @@ registerIpcMainHandle<IpcMainHandle>({
},

RESTART_ENGINE: async (_, { engineId }) => {
return engineProcessManager.restartEngine(engineId);
const manager = getEngineProcessManager();
return manager.restartEngine(engineId);
Hiroshiba marked this conversation as resolved.
Show resolved Hide resolved
},

OPEN_ENGINE_DIRECTORY: async (_, { engineId }) => {
Expand Down
16 changes: 16 additions & 0 deletions src/backend/electron/manager/RuntimeInfoManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,19 @@ export class RuntimeInfoManager {
});
}
}

let manager: RuntimeInfoManager | undefined;

export const initializeRuntimeInfoManager = (
runtimeInfoPath: string,
appVersion: string,
) => {
manager = new RuntimeInfoManager(runtimeInfoPath, appVersion);
};

export const getRuntimeInfoManager = () => {
if (manager == undefined) {
throw new Error("RuntimeInfoManager is not initialized");
}
return manager;
};
33 changes: 21 additions & 12 deletions src/backend/electron/manager/engineInfoManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { dialog } from "electron"; // FIXME: ここでelectronをimportするの

import log from "electron-log/main";

import { getConfigManager } from "../electronConfig";
import {
EngineInfo,
EngineDirValidationResult,
Expand All @@ -14,7 +15,6 @@ import {
minimumEngineManifestSchema,
} from "@/type/preload";
import { AltPortInfos } from "@/store/type";
import { BaseConfigManager } from "@/backend/common/ConfigManager";
import { loadEnvEngineInfos } from "@/domain/defaultEngine/envEngineInfo";

/**
Expand Down Expand Up @@ -45,19 +45,13 @@ function fetchDefaultEngineInfos(defaultEngineDir: string): EngineInfo[] {

/** エンジンの情報を管理するクラス */
export class EngineInfoManager {
configManager: BaseConfigManager;
defaultEngineDir: string;
vvppEngineDir: string;

/** 代替ポート情報 */
public altPortInfos: AltPortInfos = {};

constructor(payload: {
configManager: BaseConfigManager;
defaultEngineDir: string;
vvppEngineDir: string;
}) {
this.configManager = payload.configManager;
constructor(payload: { defaultEngineDir: string; vvppEngineDir: string }) {
this.defaultEngineDir = payload.defaultEngineDir;
this.vvppEngineDir = payload.vvppEngineDir;
}
Expand Down Expand Up @@ -114,8 +108,9 @@ export class EngineInfoManager {
log.log(`Failed to load engine: ${result}, ${engineDir}`);
}
}
const configManager = getConfigManager();
// FIXME: この関数の引数でregisteredEngineDirsを受け取り、動かないエンジンをreturnして、EngineManager外でconfig.setする
for (const engineDir of this.configManager.get("registeredEngineDirs")) {
for (const engineDir of configManager.get("registeredEngineDirs")) {
const result = addEngine(engineDir, "path");
if (result !== "ok") {
log.log(`Failed to load engine: ${result}, ${engineDir}`);
Expand All @@ -125,9 +120,9 @@ export class EngineInfoManager {
"エンジンの読み込みに失敗しました。",
`${engineDir}を読み込めませんでした。このエンジンは削除されます。`,
);
this.configManager.set(
configManager.set(
"registeredEngineDirs",
this.configManager
configManager
.get("registeredEngineDirs")
.filter((p) => p !== engineDir),
);
Expand Down Expand Up @@ -221,4 +216,18 @@ export class EngineInfoManager {
}
}

export default EngineInfoManager;
let manager: EngineInfoManager | undefined;

export const initializeEngineInfoManager = (payload: {
defaultEngineDir: string;
vvppEngineDir: string;
}) => {
manager = new EngineInfoManager(payload);
};

export const getEngineInfoManager = () => {
if (manager == undefined) {
throw new Error("EngineInfoManager is not initialized");
}
return manager;
};
Loading
Loading