Fix ticket page 500 from unbounded audit timeline (#112)
Lint / PHP (phpcs PSR-12) (push) Successful in 21s
Lint / JS (eslint) (push) Successful in 8s
Lint / PHP requirements (version + extensions) (push) Successful in 20s
Lint / Notify on failure (push) Skipped
Security / PHP Security (semgrep) (push) Successful in 1m22s
Lint / Deploy (push) Successful in 4s

A ticket updated by hwmonDaemon had ~52k audit rows; getTicketTimeline()
loaded all of them and exhausted PHP's 128MB memory limit, so the ticket
page returned 500. Not related to the MCP server.

- getTicketTimeline() takes a limit (newest first). The ticket page shows
  the latest 500 events with a note when older ones are omitted; the JSON
  export caps at 5000.
- create_ticket_api.php: the description is refreshed on every run, and
  that alone wrote a reason-only audit row every few minutes per open
  ticket. Audit only real title/priority changes.
- create_ticket_api.php: after creating a brand-new ticket the dedup retry
  loop fell through into a second iteration on a closed connection,
  appending a 500 error body after the success response. Exit instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MGDKHiU5RJdo3dqQUDow3X
This commit is contained in:
2026-09-25 15:34:44 -04:00
co-authored by Claude Opus 5.5
parent dad066cb32
commit ad201691e4
5 changed files with 37 additions and 10 deletions
+15 -4
View File
@@ -328,10 +328,17 @@ for ($dedupAttempt = 1; $dedupAttempt <= $maxDedupAttempts; $dedupAttempt++) {
$commentStmt->close();
}
$auditLog->log($userId, 'update', 'ticket', $existingId, array_merge(
array_diff_key($changes, ['description_refreshed' => true]),
['reason' => 'auto-updated by hwmonDaemon (condition worsened)']
));
// Audit only real title/priority changes. The description is
// refreshed on every run, and logging that alone wrote a
// reason-only row every few minutes per open ticket — 50k+ rows
// on one ticket, which broke its page (tinker_tickets#112).
$auditedChanges = array_diff_key($changes, ['description_refreshed' => true]);
if (!empty($auditedChanges)) {
$auditLog->log($userId, 'update', 'ticket', $existingId, array_merge(
$auditedChanges,
['reason' => 'auto-updated by hwmonDaemon (condition worsened)']
));
}
// Only notify on priority escalation — title-only updates (e.g. rising
// Power_On_Hours counter) should not generate a Matrix ping every hour.
@@ -581,4 +588,8 @@ for ($dedupAttempt = 1; $dedupAttempt <= $maxDedupAttempts; $dedupAttempt++) {
http_response_code(500);
echo json_encode(['success' => false, 'error' => 'Internal server error']);
}
// Done — only the deadlock `continue` above may run the loop again.
// Falling through re-entered it on a closed connection, appending a
// 500 error body after the success response for every new ticket.
exit;
}