From cc9f6ae7df9ced8b8194cbd3165c0a30eff95379 Mon Sep 17 00:00:00 2001 From: Guangcong Luo Date: Wed, 15 Nov 2023 23:56:31 +0000 Subject: [PATCH] Make Replays work better on database failures I haven't done anything about the database issues, yet, but this makes it so database issues don't screw up the UI, and also gives a slightly nicer error message. --- replay.pokemonshowdown.com/index.template.php | 2 - replay.pokemonshowdown.com/replay.php | 64 ------------------- replay.pokemonshowdown.com/replays.lib.php | 3 +- .../src/replays-battle.tsx | 47 ++++++++------ 4 files changed, 29 insertions(+), 87 deletions(-) delete mode 100644 replay.pokemonshowdown.com/replay.php diff --git a/replay.pokemonshowdown.com/index.template.php b/replay.pokemonshowdown.com/index.template.php index 2e7c13ceac..b27fbe386c 100644 --- a/replay.pokemonshowdown.com/index.template.php +++ b/replay.pokemonshowdown.com/index.template.php @@ -20,8 +20,6 @@ $manage = false; -require_once 'replays.lib.php'; - $replay = null; $id = $_REQUEST['name'] ?? ''; $password = ''; diff --git a/replay.pokemonshowdown.com/replay.php b/replay.pokemonshowdown.com/replay.php deleted file mode 100644 index fb35465066..0000000000 --- a/replay.pokemonshowdown.com/replay.php +++ /dev/null @@ -1,64 +0,0 @@ - - * @license MIT - */ - -error_reporting(E_ALL); -ini_set('display_errors', TRUE); -ini_set('display_startup_errors', TRUE); - -$manage = false; - -require_once 'replays.lib.php'; - -$replay = null; -$id = $_REQUEST['name'] ?? ''; -$password = ''; - -$fullid = $id; -if (substr($id, -2) === 'pw') { - $dashpos = strrpos($id, '-'); - $password = substr($id, $dashpos + 1, -2); - $id = substr($id, 0, $dashpos); - // die($id . ' ' . $password); -} - -// $forcecache = isset($_REQUEST['forcecache8723']); -$forcecache = false; -if ($id) { - if (file_exists('caches/' . $id . '.inc.php')) { - include 'caches/' . $id . '.inc.php'; - $replay['formatid'] = ''; - $cached = true; - } else { - require_once 'replays.lib.php'; - if (!$Replays->db && !$forcecache) { - header('HTTP/1.1 503 Service Unavailable'); - die(); - } - $replay = $Replays->exists($id, $forcecache); - } -} -if (!$replay) { - header('HTTP/1.1 404 Not Found'); - include '404.html'; - die(); -} -if ($replay['password'] ?? null) { - if ($password !== $replay['password']) { - header('HTTP/1.1 404 Not Found'); - include '404.html'; - die(); - } -} - -include 'index.html'; diff --git a/replay.pokemonshowdown.com/replays.lib.php b/replay.pokemonshowdown.com/replays.lib.php index db8cf32f90..7d2e34e827 100644 --- a/replay.pokemonshowdown.com/replays.lib.php +++ b/replay.pokemonshowdown.com/replays.lib.php @@ -24,7 +24,8 @@ function init() { ); } catch (PDOException $e) { // this error message contains the database password for some reason :| - die("Could not connect"); + header('HTTP/1.1 503 Service Unavailable'); + die("Database overloaded, please try again later"); } $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); diff --git a/replay.pokemonshowdown.com/src/replays-battle.tsx b/replay.pokemonshowdown.com/src/replays-battle.tsx index bfb0264ba6..4292f8cf41 100644 --- a/replay.pokemonshowdown.com/src/replays-battle.tsx +++ b/replay.pokemonshowdown.com/src/replays-battle.tsx @@ -70,6 +70,7 @@ export class BattlePanel extends preact.Component<{id: string}> { private: number; password: string; } | null | undefined = undefined; + resultError = ''; battle: Battle | null; /** debug purposes */ lastUsedKeyCode = '0'; @@ -92,17 +93,21 @@ export class BattlePanel extends preact.Component<{id: string}> { if (this.battle) this.battle.destroy(); this.battle = null; this.result = undefined; + this.resultError = ''; + this.forceUpdate(); const elem = document.getElementById(`replaydata-${id}`); if (elem) { - this.loadResult(elem.innerText, id); + // we actually do need to wait for that update to finish so + // loadResult definitely has access to $frame and $logFrame + setTimeout(() => this.loadResult(elem.innerText, id), 1); return; } Net(`/${this.stripQuery(id)}.json`).get().then(result => { this.loadResult(result, id); - }).catch(_ => { - this.loadResult('', id); + }).catch(err => { + this.loadResult(err.statusCode === 404 ? '' : String(err?.body || ''), id); }); } loadResult(result: string, id: string) { @@ -131,8 +136,9 @@ export class BattlePanel extends preact.Component<{id: string}> { if (query.turn || query.t) { this.battle.seekTurn(parseInt(query.turn || query.t, 10)); } - } catch { + } catch (err) { this.result = null; + this.resultError = result.startsWith('{') ? err.toString() : result; } this.forceUpdate(); } @@ -353,20 +359,21 @@ export class BattlePanel extends preact.Component<{id: string}> { e?.preventDefault(); this.forceUpdate(); }; - renderNotFound() { - return
- {/*
- - - -
-
- - - - - -
*/} + renderError(position: any) { + if (this.resultError) { + return
+

Error

+

+ {this.resultError} +

+
; + } + + // In theory, this should almost never happen, because Replays will + // never link to a nonexistent replay, but this might happen if e.g. + // a replay gets deleted or made private after you searched for it + // but before you clicked it. + return
@@ -493,8 +500,6 @@ export class BattlePanel extends preact.Component<{id: string}> {
; } override render() { - if (this.result === null) return this.renderNotFound(); - let position: any = {}; if (PSRouter.showingLeft()) { if (PSRouter.stickyRight) { @@ -504,6 +509,8 @@ export class BattlePanel extends preact.Component<{id: string}> { } } + if (this.result === null) return this.renderError(position); + return