diff options
| author | Party Wumpus <48649272+PartyWumpus@users.noreply.github.com> | 2024-02-22 16:38:50 +0000 |
|---|---|---|
| committer | Party Wumpus <48649272+PartyWumpus@users.noreply.github.com> | 2024-02-22 16:38:50 +0000 |
| commit | 89a4a69f6da706a0cd8c4036bc1aa4c6e44f6e11 (patch) | |
| tree | e6e0409dd6efa7eaba08bff0bcd50143dcda1d24 | |
| parent | a449181802f05c0d1bd1a318741ce347e993d6f7 (diff) | |
| download | decky-loader-89a4a69f6da706a0cd8c4036bc1aa4c6e44f6e11.tar.gz decky-loader-89a4a69f6da706a0cd8c4036bc1aa4c6e44f6e11.zip | |
make frontend -> backend errors actually work
| -rw-r--r-- | backend/decky_loader/updater.py | 1 | ||||
| -rw-r--r-- | backend/decky_loader/wsrouter.py | 26 | ||||
| -rw-r--r-- | frontend/src/components/settings/pages/testing/index.tsx | 10 | ||||
| -rw-r--r-- | frontend/src/wsrouter.ts | 17 |
4 files changed, 40 insertions, 14 deletions
diff --git a/backend/decky_loader/updater.py b/backend/decky_loader/updater.py index 6355fcc7..268ab240 100644 --- a/backend/decky_loader/updater.py +++ b/backend/decky_loader/updater.py @@ -282,3 +282,4 @@ class Updater: await self.download_decky_binary(down_link, f'PR-{pr_id}' , True) else: logger.error("workflow run not found", str(works)) + raise Exception("Workflow run not found.") diff --git a/backend/decky_loader/wsrouter.py b/backend/decky_loader/wsrouter.py index 918b74bc..9f8b194d 100644 --- a/backend/decky_loader/wsrouter.py +++ b/backend/decky_loader/wsrouter.py @@ -60,15 +60,25 @@ class WSRouter: async def _call_route(self, route: str, args: ..., call_id: int): instance_id = self.instance_id - res = await self.routes[route](*args) + error = None + try: + res = await self.routes[route](*args) + except Exception as err: + error = {"name":err.__class__.__name__, "message":str(err), "traceback":format_exc()} + res = None + if instance_id != self.instance_id: try: self.logger.warn("Ignoring %s reply from stale instance %d with args %s and response %s", route, instance_id, args, res) except: self.logger.warn("Ignoring %s reply from stale instance %d (failed to log event data)", route, instance_id) finally: - return - await self.write({"type": MessageType.REPLY.value, "id": call_id, "result": res}) + return + + if error: + await self.write({"type": MessageType.ERROR.value, "id": call_id, "error": error}) + else: + await self.write({"type": MessageType.REPLY.value, "id": call_id, "result": res}) async def handle(self, request: Request): # Auth is a query param as JS WebSocket doesn't support headers @@ -103,14 +113,12 @@ class WSRouter: case MessageType.CALL.value: # do stuff with the message if data["route"] in self.routes: - try: - self.logger.debug(f'Started PY call {data["route"]} ID {data["id"]}') - create_task(self._call_route(data["route"], data["args"], data["id"])) - except: - create_task(self.write({"type": MessageType.ERROR.value, "id": data["id"], "error": format_exc()})) + self.logger.debug(f'Started PY call {data["route"]} ID {data["id"]}') + create_task(self._call_route(data["route"], data["args"], data["id"])) else: + error = {"error":"Route " + data["route"] + " does not exist.", "name": "NameMeOrNoneIDK", "traceback": None} # Dunno why but fstring doesnt work here - create_task(self.write({"type": MessageType.ERROR.value, "id": data["id"], "error": "Route " + data["route"] + " does not exist."})) + create_task(self.write({"type": MessageType.ERROR.value, "id": data["id"], "message": error})) case _: self.logger.error("Unknown message type", data) finally: diff --git a/frontend/src/components/settings/pages/testing/index.tsx b/frontend/src/components/settings/pages/testing/index.tsx index cdf51c71..4fe0f240 100644 --- a/frontend/src/components/settings/pages/testing/index.tsx +++ b/frontend/src/components/settings/pages/testing/index.tsx @@ -70,8 +70,14 @@ export default function TestingVersionList() { <Focusable style={{ height: '40px', marginLeft: 'auto', display: 'flex' }}> <DialogButton style={{ height: '40px', minWidth: '60px', marginRight: '10px' }} - onClick={() => { - downloadTestingVersion(version.id, version.head_sha); + onClick={async () => { + try { + await downloadTestingVersion(version.id, version.head_sha); + } catch (e) { + if (e instanceof Error) { + DeckyPluginLoader.toaster.toast({ title: 'Error Installing PR', body: e.message }); + } + } setSetting('branch', UpdateBranch.Testing); }} > diff --git a/frontend/src/wsrouter.ts b/frontend/src/wsrouter.ts index 37df4262..e3a6900b 100644 --- a/frontend/src/wsrouter.ts +++ b/frontend/src/wsrouter.ts @@ -30,10 +30,20 @@ interface ReplyMessage { interface ErrorMessage { type: MessageType.ERROR; - error: any; + error: { name: string; message: string; traceback: string | null }; id: number; } +export class PyError extends Error { + pythonTraceback: string | null; + + constructor(name: string, message: string, traceback: string | null) { + super(message); + this.name = `Python ${name}`; + this.pythonTraceback = traceback; + } +} + interface EventMessage { type: MessageType.EVENT; event: string; @@ -45,7 +55,7 @@ type Message = CallMessage | ReplyMessage | ErrorMessage | EventMessage; // Helper to resolve a promise from the outside interface PromiseResolver<T> { resolve: (res: T) => void; - reject: (error: string) => void; + reject: (error: PyError) => void; promise: Promise<T>; } @@ -124,7 +134,8 @@ export class WSRouter extends Logger { case MessageType.ERROR: if (this.runningCalls.has(data.id)) { - this.runningCalls.get(data.id)!.reject(data.error); + let err = new PyError(data.error.name, data.error.message, data.error.traceback); + this.runningCalls.get(data.id)!.reject(err); this.runningCalls.delete(data.id); this.debug(`Rejected PY call ${data.id} with error`, data.error); } |
