[feature-274] Use CustomError class for launch errors

This commit is contained in:
MathieuG-P
2023-11-06 17:06:56 +01:00
parent d69a55de7d
commit d7a885f3b8
3 changed files with 49 additions and 31 deletions
@@ -1,15 +1,16 @@
import { Observable, ReplaySubject, catchError, lastValueFrom, of, take, timeout } from "rxjs";
import { StoreLauncherInterface } from "./store-launcher.interface";
import { BSLaunchError, BSLaunchErrorData, BSLaunchEvent, BSLaunchEventData, LaunchOption } from "../../../shared/models/bs-launch";
import { BSLaunchError, BSLaunchEvent, BSLaunchEventData, LaunchOption } from "../../../shared/models/bs-launch";
import { OculusService } from "../oculus.service";
import { BS_EXECUTABLE, OCULUS_BS_BACKUP_DIR, OCULUS_BS_DIR } from "../../constants";
import path from "path";
import log from "electron-log";
import { sToMs } from "../../../shared/helpers/time.helpers";
import { lstat, pathExists, readdir, rename, stat, symlink, unlink } from "fs-extra";
import { pathExists, readdir, rename, symlink, unlink } from "fs-extra";
import { AbstractLauncherService } from "./abstract-launcher.service";
import { taskRunning } from "../../helpers/os.helpers";
import { isJunction } from "../../helpers/fs.helpers";
import { CustomError } from "../../../shared/models/exceptions/custom-error.class";
export class OculusLauncherService extends AbstractLauncherService implements StoreLauncherInterface {
@@ -84,12 +85,15 @@ export class OculusLauncherService extends AbstractLauncherService implements St
return rename(bsFolderBackupPath, originalPath);
}
// TODO : Convert all errors to CustomError
public launch(launchOptions: LaunchOption): Observable<BSLaunchEventData> {
const prepareOriginalVersion: () => Promise<string> = async () => {
await this.restoreOriginalBeatSaber();
return this.oculus.getGameFolder(OCULUS_BS_DIR);
const bsPath = this.oculus.getGameFolder(OCULUS_BS_DIR);
if(!bsPath){
throw new Error("Oculus Beat Saber path not found");
}
return bsPath;
}
const prepareDowngradedVersion: () => Promise<string> = async () => {
@@ -115,29 +119,37 @@ export class OculusLauncherService extends AbstractLauncherService implements St
(async () => {
// Cannot start multiple instances of Beat Saber with Oculus
const bsRunning = await taskRunning(BS_EXECUTABLE);
const bsRunning = await taskRunning(BS_EXECUTABLE).catch(() => false);
if(bsRunning){
throw ({type: BSLaunchError.BS_ALREADY_RUNNING, data: bsRunning}) as BSLaunchErrorData;
throw CustomError.fromError(new Error("Cannot start two instance of Beat Saber for Oculus"), BSLaunchError.BS_ALREADY_RUNNING);
}
// Remove previously symlinks created by BSM
await this.deleteBsSymlinks().catch(log.error);
await this.deleteBsSymlinks().catch(err => log.error("Error while deleting BSM symlinks", err));
const bsPath = await (launchOptions.version.oculus ? prepareOriginalVersion() : prepareDowngradedVersion());
if(!bsPath){
throw ({type: BSLaunchError.BS_NOT_FOUND}) as BSLaunchErrorData;
}
const bsPath = await (launchOptions.version.oculus ? prepareOriginalVersion() : prepareDowngradedVersion())
.catch(err => CustomError.throw(err, BSLaunchError.OCULUS_LIB_NOT_FOUND));
// Launch Beat Saber
const exePath = path.join(bsPath, "Beat Saber.exe");
const exePath = path.join(bsPath, BS_EXECUTABLE);
if(!(await pathExists(exePath))){
throw CustomError.fromError(new Error(`BS Path not exist ${bsPath}`), BSLaunchError.BS_NOT_FOUND);
}
obs.next({type: BSLaunchEvent.BS_LAUNCHING});
return this.launchBs(exePath, this.buildBsLaunchArgs(launchOptions)).catch(err => {
throw ({type: BSLaunchError.BS_EXIT_ERROR, data: err}) as BSLaunchErrorData;
throw CustomError.fromError(err, BSLaunchError.BS_EXIT_ERROR);
});
})().catch(err => {
obs.error(err);
})().then(exitCode => {
log.info("BS process exit code", exitCode);
}).catch(err => {
if(err instanceof CustomError){
obs.error(err);
} else {
obs.error(CustomError.fromError(err, BSLaunchError.UNKNOWN_ERROR));
}
}).finally(() => {
obs.complete();
})
@@ -1,5 +1,5 @@
import { Observable } from "rxjs";
import { BSLaunchError, BSLaunchErrorData, BSLaunchEvent, BSLaunchEventData, BSLaunchWarning, LaunchOption } from "../../../shared/models/bs-launch";
import { BSLaunchError, BSLaunchEvent, BSLaunchEventData, BSLaunchWarning, LaunchOption } from "../../../shared/models/bs-launch";
import { StoreLauncherInterface } from "./store-launcher.interface";
import { pathExists, rename } from "fs-extra";
import { SteamService } from "../steam.service";
@@ -7,6 +7,7 @@ import path from "path";
import { BS_APP_ID, BS_EXECUTABLE, STEAMVR_APP_ID } from "../../constants";
import log from "electron-log";
import { AbstractLauncherService } from "./abstract-launcher.service";
import { CustomError } from "../../../shared/models/exceptions/custom-error.class";
export class SteamLauncherService extends AbstractLauncherService implements StoreLauncherInterface{
@@ -52,8 +53,7 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto
log.error("Error while restoring SteamVR", err);
});
}
// TODO : Convert all errors to CustomError
public launch(launchOptions: LaunchOption): Observable<BSLaunchEventData>{
return new Observable<BSLaunchEventData>(obs => {(async () => {
@@ -62,11 +62,11 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto
const exePath = path.join(bsFolderPath, BS_EXECUTABLE);
if(!(await pathExists(exePath))){
return obs.error({type: BSLaunchError.BS_NOT_FOUND} as BSLaunchErrorData);
throw CustomError.fromError(new Error(`Path not exist : ${exePath}`), BSLaunchError.BS_NOT_FOUND);
}
// Open Steam if not running
if(!launchOptions.version.oculus && !(await this.steam.steamRunning())){
if(!(await this.steam.steamRunning())){
obs.next({type: BSLaunchEvent.STEAM_LAUNCHING});
await this.steam.openSteam().then(() => {
@@ -78,22 +78,22 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto
}
// Backup SteamVR when desktop mode is enabled
if(!launchOptions.version.oculus && launchOptions.desktop){
if(launchOptions.desktop){
await this.backupSteamVR().catch(() => {
return this.restoreSteamVR();
});
} else if(!launchOptions.version.oculus){
await this.restoreSteamVR();
} else {
await this.restoreSteamVR().catch(log.error);
}
const launchArgs = this.buildBsLaunchArgs(launchOptions);
obs.next({type: BSLaunchEvent.BS_LAUNCHING});
this.launchBs(exePath, launchArgs, { env: {...process.env, "SteamAppId": BS_APP_ID} }).then(exitCode => {
await this.launchBs(exePath, launchArgs, { env: {...process.env, "SteamAppId": BS_APP_ID} }).then(exitCode => {
log.info("BS process exit code", exitCode);
}).catch(err => {
obs.error({type: BSLaunchError.BS_EXIT_ERROR, data: err} as BSLaunchErrorData);
throw CustomError.fromError(err, BSLaunchError.BS_EXIT_ERROR);
}).finally(() => {
this.restoreSteamVR().catch(log.error);
});
@@ -101,7 +101,11 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto
})().then(() => {
obs.complete();
}).catch(err => {
obs.error({type: BSLaunchError.UNKNOWN_ERROR, data: err} as BSLaunchErrorData);
if(err instanceof CustomError){
obs.error(err);
} else {
obs.error(CustomError.fromError(err, BSLaunchError.UNKNOWN_ERROR));
}
})});
}
+6 -4
View File
@@ -1,4 +1,4 @@
import { LaunchOption, BSLaunchEvent, BSLaunchWarning, BSLaunchEventData, BSLaunchErrorData, BSLaunchError } from "shared/models/bs-launch";
import { LaunchOption, BSLaunchEvent, BSLaunchWarning, BSLaunchEventData, BSLaunchError } from "shared/models/bs-launch";
import { BSVersion } from 'shared/bs-version.interface';
import { IpcService } from "./ipc.service";
import { NotificationService } from "./notification.service";
@@ -8,6 +8,8 @@ import { ThemeService } from "./theme.service";
import { BsStore } from "shared/models/bs-store.enum";
import { ModalExitCode, ModalService } from "./modale.service";
import { OriginalOculusVersionBackupModal } from "renderer/components/modal/modal-types/original-oculus-version-backup.modal";
import { CustomError } from "shared/models/exceptions/custom-error.class";
import { sToMs } from "shared/helpers/time.helpers";
export class BSLauncherService {
private static instance: BSLauncherService;
@@ -59,11 +61,11 @@ export class BSLauncherService {
if(eventToFilter.includes(event.type)){ return; }
this.notificationService.notifySuccess({title: `notifications.bs-launch.success.titles.${event.type}`, desc: `notifications.bs-launch.success.msg.${event.type}`});
},
error: (err: BSLaunchErrorData) => { // TODO : Convert all errors to CustomError
if(!Object.values(BSLaunchError).includes(err.type)){
error: (err: CustomError) => {
if(!err?.code || !Object.values(BSLaunchError).includes(err.code as BSLaunchError)){
this.notificationService.notifyError({title: "notifications.bs-launch.errors.titles.UNKNOWN_ERROR", desc: "notifications.bs-launch.errors.msg.UNKNOWN_ERROR"});
} else {
this.notificationService.notifyError({title: `notifications.bs-launch.errors.titles.${err.type}`, desc: `notifications.bs-launch.errors.msg.${err.type}`})
this.notificationService.notifyError({title: `notifications.bs-launch.errors.titles.${err.code}`, desc: `notifications.bs-launch.errors.msg.${err.code}`, duration: sToMs(9)})
}
}
}))