Skip to content

Commit

Permalink
refactor: エンジン情報管理のロジックを改善し、エンジン情報の取得メソッドを整理
Browse files Browse the repository at this point in the history
  • Loading branch information
Hiroshiba committed Nov 6, 2024
1 parent 3b6bd19 commit 166ea3d
Showing 1 changed file with 105 additions and 73 deletions.
178 changes: 105 additions & 73 deletions src/backend/electron/manager/engineInfoManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,85 +15,103 @@ import {
minimumEngineManifestSchema,
} from "@/type/preload";
import { AltPortInfos } from "@/store/type";
import { UnreachableError } from "@/type/utility";
import { loadEnvEngineInfos } from "@/domain/defaultEngine/envEngineInfo";
import { failure, Result, success } from "@/type/result";

/**
* デフォルトエンジンの情報を取得する
*/
function fetchDefaultEngineInfos(defaultEngineDir: string): EngineInfo[] {
// TODO: envから直接ではなく、envに書いたengine_manifest.jsonから情報を得るようにする
const engines = loadEnvEngineInfos();

return engines.map((engineInfo) => {
const { protocol, hostname, port, pathname } = new URL(engineInfo.host);
return {
...engineInfo,
protocol,
hostname,
defaultPort: port,
pathname: pathname === "/" ? "" : pathname,
isDefault: true,
type: "path",
executionFilePath: path.resolve(engineInfo.executionFilePath),
path:
engineInfo.path == undefined
? undefined
: path.resolve(defaultEngineDir, engineInfo.path),
} satisfies EngineInfo;
});
}

/** エンジンの情報を管理するクラス */
/** 利用可能なエンジンの情報を管理するクラス */
export class EngineInfoManager {
defaultEngineDir: string;
vvppEngineDir: string;

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

private envEngineInfos = loadEnvEngineInfos();

constructor(payload: { defaultEngineDir: string; vvppEngineDir: string }) {
this.defaultEngineDir = payload.defaultEngineDir;
this.vvppEngineDir = payload.vvppEngineDir;
}

/** デフォルトエンジンかどうかを判定する */
private isDefaultEngine(engineId: EngineId): boolean {
return this.envEngineInfos.some((e) => e.uuid === engineId);
}

/** エンジンディレクトリからエンジン情報を読み込む */
private loadEngineInfo(
engineDir: string,
type: "vvpp" | "path",
): Result<EngineInfo, "manifestNotFound" | "manifestParseError"> {
const manifestPath = path.join(engineDir, "engine_manifest.json");
if (!fs.existsSync(manifestPath)) {
return failure("manifestNotFound", new Error("manifest not found"));
}
let manifest: MinimumEngineManifestType;
try {
manifest = minimumEngineManifestSchema.parse(
JSON.parse(fs.readFileSync(manifestPath, { encoding: "utf8" })),
);
} catch (e) {
if (e instanceof Error) {
return failure("manifestParseError", e);
} else {
throw new UnreachableError();
}
}

const [command, ...args] = shlex.split(manifest.command);

const engineInfo = {
uuid: manifest.uuid,
protocol: "http:",
hostname: "127.0.0.1",
defaultPort: manifest.port.toString(),
pathname: "",
name: manifest.name,
path: engineDir,
executionEnabled: true,
executionFilePath: path.join(engineDir, command),
executionArgs: args,
type,
isDefault: this.isDefaultEngine(manifest.uuid),
} satisfies EngineInfo;
return success(engineInfo);
}

/**
* 追加エンジンの一覧を取得する
* FIXME: store.get("registeredEngineDirs")への副作用をEngineManager外に移動する
* .envにあるエンジンの情報を取得する
* ダウンロードが必要なものは除外されている。
*/
private fetchAdditionalEngineInfos(): EngineInfo[] {
const engines: EngineInfo[] = [];
const addEngine = (engineDir: string, type: "vvpp" | "path") => {
const manifestPath = path.join(engineDir, "engine_manifest.json");
if (!fs.existsSync(manifestPath)) {
return "manifestNotFound";
}
let manifest: MinimumEngineManifestType;
try {
manifest = minimumEngineManifestSchema.parse(
JSON.parse(fs.readFileSync(manifestPath, { encoding: "utf8" })),
);
} catch (e) {
return "manifestParseError";
}
private fetchEnvEngineInfos(): EngineInfo[] {
// TODO: envから直接ではなく、envに書いたengine_manifest.jsonから情報を得るようにする
const engines = loadEnvEngineInfos();

return engines.map((engineInfo) => {
const { protocol, hostname, port, pathname } = new URL(engineInfo.host);
return {
...engineInfo,
protocol,
hostname,
defaultPort: port,
pathname: pathname === "/" ? "" : pathname,
isDefault: true,
type: "path",
executionFilePath: path.resolve(engineInfo.executionFilePath),
path:
engineInfo.path == undefined
? undefined
: path.resolve(this.defaultEngineDir, engineInfo.path),
} satisfies EngineInfo;
});
}

const [command, ...args] = shlex.split(manifest.command);

engines.push({
uuid: manifest.uuid,
protocol: "http:",
hostname: "127.0.0.1",
defaultPort: manifest.port.toString(),
pathname: "",
name: manifest.name,
path: engineDir,
executionEnabled: true,
executionFilePath: path.join(engineDir, command),
executionArgs: args,
type,
isDefault: false,
} satisfies EngineInfo);
return "ok";
};
/**
* VVPPエンジン情報の一覧を取得する。
*/
private fetchVvppEngineInfos(): EngineInfo[] {
const engineInfos: EngineInfo[] = [];
for (const dirName of fs.readdirSync(this.vvppEngineDir)) {
const engineDir = path.join(this.vvppEngineDir, dirName);
if (!fs.statSync(engineDir).isDirectory()) {
Expand All @@ -103,17 +121,28 @@ export class EngineInfoManager {
if (dirName === ".tmp") {
continue;
}
const result = addEngine(engineDir, "vvpp");
if (result !== "ok") {
log.log(`Failed to load engine: ${result}, ${engineDir}`);
const result = this.loadEngineInfo(engineDir, "vvpp");
if (!result.ok) {
log.log(`Failed to load engine: ${result.code}, ${engineDir}`);
continue;
}
engineInfos.push(result.value);
}
return engineInfos;
}

/**
* 設定で登録したエンジン情報を取得する。
* FIXME: store.get("registeredEngineDirs")への副作用をEngineManager外に移動する
*/
private fetchRegisteredEngineInfos(): EngineInfo[] {
const configManager = getConfigManager();
// FIXME: この関数の引数でregisteredEngineDirsを受け取り、動かないエンジンをreturnして、EngineManager外でconfig.setする

const engineInfos: EngineInfo[] = [];
for (const engineDir of configManager.get("registeredEngineDirs")) {
const result = addEngine(engineDir, "path");
if (result !== "ok") {
log.log(`Failed to load engine: ${result}, ${engineDir}`);
const result = this.loadEngineInfo(engineDir, "path");
if (!result.ok) {
log.log(`Failed to load engine: ${result.code}, ${engineDir}`);
// 動かないエンジンは追加できないので削除
// FIXME: エンジン管理UIで削除可能にする
dialog.showErrorBox(
Expand All @@ -126,18 +155,21 @@ export class EngineInfoManager {
.get("registeredEngineDirs")
.filter((p) => p !== engineDir),
);
continue;
}
engineInfos.push(result.value);
}
return engines;
return engineInfos;
}

/**
* 全てのエンジンの一覧を取得する。デフォルトエンジン+追加エンジン。
* 全てのエンジンの一覧を取得する。
*/
fetchEngineInfos(): EngineInfo[] {
const engineInfos = [
...fetchDefaultEngineInfos(this.defaultEngineDir),
...this.fetchAdditionalEngineInfos(),
...this.fetchEnvEngineInfos(),
...this.fetchVvppEngineInfos(),
...this.fetchRegisteredEngineInfos(),
];
return engineInfos;
}
Expand Down

0 comments on commit 166ea3d

Please sign in to comment.