Retry Dead Letter Reporter
Summarizes failed queued jobs or webhooks after retry exhaustion.
Function signature
ogBuildDeadLetterReport(failed_jobs = array(), options = array())
Categories
- APIs and Webhooks
Parameters
failed_jobsFailed queue records.optionsReport grouping and redaction options. Recognized keys: `group_by`.Return value
Short public-safe status message.
- total_failed
- groups
- rows
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, policy arrays, URLs, signatures, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Summarizes failed queued jobs or webhooks after retry exhaustion.
*
* Payloads are summarized and redacted so admin screens can show useful failure details without
* exposing secrets or full request bodies.
*
* @param array $failed_jobs Failed queue records.
* @param array $options Report grouping and redaction options.
* @return array Dead-letter report data.
*/
function ogBuildDeadLetterReport($failed_jobs = array(), $options = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($failed_jobs)) {
$result['message'] = 'Failed jobs must be an array.';
return $result;
}
if (!is_array($options)) {
$options = array();
}
$group_by = 'type';
if (!empty($options['group_by'])) {
$group_by = preg_replace('/[^a-zA-Z0-9_]/', '', (string)$options['group_by']);
}
$groups = array();
$rows = array();
foreach ($failed_jobs as $job) {
if (!is_array($job)) {
continue;
}
$group_value = 'unknown';
if (!empty($job[$group_by])) {
$group_value = (string)$job[$group_by];
}
if (empty($groups[$group_value])) {
$groups[$group_value] = array('count' => 0, 'last_failed_at' => '', 'retryable' => 0);
}
$groups[$group_value]['count']++;
$failed_at = '';
if (!empty($job['failed_at'])) {
$failed_at = (string)$job['failed_at'];
$groups[$group_value]['last_failed_at'] = $failed_at;
}
$attempts = 0;
if (!empty($job['attempts'])) {
$attempts = (int)$job['attempts'];
}
$max_attempts = 0;
if (!empty($job['max_attempts'])) {
$max_attempts = (int)$job['max_attempts'];
}
$retryable = $max_attempts <= 0 || $attempts < $max_attempts;
if ($retryable) {
$groups[$group_value]['retryable']++;
}
$id = '';
if (!empty($job['id'])) {
$id = (string)$job['id'];
}
$type = '';
if (!empty($job['type'])) {
$type = (string)$job['type'];
}
$error = '';
if (!empty($job['error'])) {
$error = substr((string)$job['error'], 0, 300);
}
$rows[] = array(
'id' => $id,
'type' => $type,
'error' => $error,
'attempts' => $attempts,
'retryable' => $retryable,
'failed_at' => $failed_at
);
}
$result['success'] = true;
$result['message'] = 'Dead-letter report built.';
$result['data'] = array(
'total_failed' => count($rows),
'groups' => $groups,
'rows' => $rows
);
return $result;
}