From 63c6cc69723ee6cf4964c68f6b1967cc58bf19b0 Mon Sep 17 00:00:00 2001 From: Keith Solomon Date: Fri, 7 Aug 2026 17:39:22 -0500 Subject: [PATCH] Replace broadcast backfill with per-entry re-fetch for running_balance --- includes/utilities.php | 54 +++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/includes/utilities.php b/includes/utilities.php index c27820e..eaeae25 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -290,21 +290,24 @@ function consoleLog( $data ) { } /** - * Backfill the running_balance column for any user rows that have NULL. + * Re-fetch the running_balance for each entry of a user by walking the + * v2 /log paginated endpoint. * - * The v2 API's `data.balance` field is the vault balance after each entry. - * If the column is missing for a row, treating it as NULL means - * MAX(running_balance) ignores it. This routine fetches the latest entry's - * balance from the API and broadcasts it to all NULL rows of the user, - * so the displayed balance becomes accurate after the first sync following - * the schema upgrade. + * For each entry the API returns, we run a single UPDATE setting that + * entry's `running_balance` to its `data.balance`. The pre-existing + * broadcast approach gave every row of a user the same value, which + * made the historical view misleading; this restores per-entry accuracy. + * + * If the user has zero rows with `running_balance IS NULL`, returns + * without making any HTTP call. On API failure, the underlying + * exception propagates to the caller's try/catch in index.php. * * @param PDO $pdo Database connection. - * @param string $user The user whose NULL rows should be backfilled. + * @param string $user The user whose NULL rows should be refilled. * * @return void */ -function backfillRunningBalances($pdo, $user) { +function refetchRunningBalances($pdo, $user) { if (!array_key_exists($user, USER_KEYS)) { throw new ApiKeyMissingException("User does not have an API key configured."); } @@ -317,25 +320,28 @@ function backfillRunningBalances($pdo, $user) { return; } - $url = 'https://api.torn.com/v2/user?selections=log&log=5850,5851&limit=1&sort=DESC'; - $responseData = executeApiCall($url, USER_KEYS[$user]); - validateApiResponse($responseData); + $updateStmt = $pdo->prepare( + 'UPDATE vault SET running_balance = :balance WHERE id = :id' + ); - if (empty($responseData['log'])) { - return; - } + $url = 'https://api.torn.com/v2/user?selections=log&log=5850,5851'; + do { + $responseData = executeApiCall($url, USER_KEYS[$user]); + validateApiResponse($responseData); - $latest = $responseData['log'][0]; - if (!isset($latest['data']['balance'])) { - return; - } + foreach ($responseData['log'] as $entry) { + $id = $entry['id'] ?? null; + if (!$id || !isset($entry['data']['balance'])) { + continue; + } - $balance = (int)$latest['data']['balance']; + $updateStmt->bindValue(':balance', (int)$entry['data']['balance']); + $updateStmt->bindValue(':id', $id); + $updateStmt->execute(); + } - $updateStmt = $pdo->prepare('UPDATE vault SET running_balance = :balance WHERE user = :user AND running_balance IS NULL'); - $updateStmt->bindValue(':balance', $balance); - $updateStmt->bindValue(':user', $user); - $updateStmt->execute(); + $url = $responseData['_metadata']['links']['next'] ?? null; + } while ($url !== null); } /**