fix(platform+admin-web): 3 bugs in delivery retry + webhooks delivery loading
Backend (delivery retry): - Use NotFoundError (404) instead of BadRequestError (400) for missing log doc - Add telegram + slack retry support (was email-only, threw error for others) Frontend (delivery page): - Add pk field to DeliveryEntry interface - Pass pk query param in retry call so backend can look up the doc - Fix handleRetry to accept full entry object instead of just id Frontend (webhooks page): - Parallelize delivery fetches with Promise.allSettled (was sequential for loop) - Significant page load improvement for subscriptions with many deliveries
This commit is contained in:
parent
f92504ceb4
commit
9180954903
@ -24,6 +24,7 @@ import {
|
||||
|
||||
interface DeliveryEntry {
|
||||
id: string;
|
||||
pk: string;
|
||||
template: string;
|
||||
recipient: string;
|
||||
channel: string;
|
||||
@ -71,8 +72,10 @@ export default function DeliveryPage() {
|
||||
void loadData();
|
||||
}, [loadData]);
|
||||
|
||||
async function handleRetry(id: string) {
|
||||
await apiFetch(`logs/${id}/retry`, { method: 'POST' });
|
||||
async function handleRetry(entry: DeliveryEntry) {
|
||||
await apiFetch(`logs/${entry.id}/retry?pk=${encodeURIComponent(entry.pk)}`, {
|
||||
method: 'POST',
|
||||
});
|
||||
loadData();
|
||||
}
|
||||
|
||||
@ -191,7 +194,7 @@ export default function DeliveryPage() {
|
||||
<TableCell>
|
||||
{e.status === 'failed' && (
|
||||
<button
|
||||
onClick={() => handleRetry(e.id)}
|
||||
onClick={() => handleRetry(e)}
|
||||
className="text-xs text-blue-600 hover:underline"
|
||||
>
|
||||
Retry
|
||||
|
||||
@ -81,21 +81,22 @@ export default function WebhooksPage() {
|
||||
: [];
|
||||
setSubs(subsList);
|
||||
|
||||
// Load deliveries per-subscription (backend only has GET /webhooks/subscriptions/:id/deliveries)
|
||||
const allDeliveries: Delivery[] = [];
|
||||
for (const sub of subsList.slice(0, 10)) {
|
||||
try {
|
||||
const dData = await apiFetch(`subscriptions/${sub.id}/deliveries`);
|
||||
const items: Delivery[] = Array.isArray(dData?.deliveries)
|
||||
? dData.deliveries
|
||||
: Array.isArray(dData)
|
||||
? dData
|
||||
: [];
|
||||
allDeliveries.push(...items);
|
||||
} catch {
|
||||
// best-effort
|
||||
}
|
||||
}
|
||||
// Load deliveries per-subscription in parallel (backend only has per-sub endpoint)
|
||||
const results = await Promise.allSettled(
|
||||
subsList.slice(0, 10).map(sub =>
|
||||
apiFetch(`subscriptions/${sub.id}/deliveries`).then((dData: Record<string, unknown>) => {
|
||||
const items: Delivery[] = Array.isArray(dData?.deliveries)
|
||||
? (dData.deliveries as Delivery[])
|
||||
: Array.isArray(dData)
|
||||
? (dData as unknown as Delivery[])
|
||||
: [];
|
||||
return items;
|
||||
})
|
||||
)
|
||||
);
|
||||
const allDeliveries = results
|
||||
.filter((r): r is PromiseFulfilledResult<Delivery[]> => r.status === 'fulfilled')
|
||||
.flatMap(r => r.value);
|
||||
setDeliveries(allDeliveries.sort((a, b) => b.createdAt.localeCompare(a.createdAt)));
|
||||
setLoading(false);
|
||||
}, []);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
import { extractAuth } from '../../lib/auth.js';
|
||||
import { BadRequestError } from '../../lib/errors.js';
|
||||
import { BadRequestError, NotFoundError } from '../../lib/errors.js';
|
||||
import {
|
||||
SendEmailSchema,
|
||||
SendSlackSchema,
|
||||
@ -130,7 +130,7 @@ export async function deliveryRoutes(app: FastifyInstance) {
|
||||
|
||||
// Look up the original log entry
|
||||
const original = await repo.getDeliveryLog(id, pk);
|
||||
if (!original) throw new BadRequestError(`Delivery log '${id}' not found`);
|
||||
if (!original) throw new NotFoundError(`Delivery log '${id}' not found`);
|
||||
if (original.status !== 'failed') {
|
||||
throw new BadRequestError(
|
||||
`Can only retry failed deliveries (current status: ${original.status})`
|
||||
@ -152,6 +152,26 @@ export async function deliveryRoutes(app: FastifyInstance) {
|
||||
return { success: result.success, messageId: result.messageId, error: result.error };
|
||||
}
|
||||
|
||||
if (original.channel === 'telegram') {
|
||||
const result = await dispatchTelegram({
|
||||
text: (original.metadata as Record<string, string>)?.text ?? original.subject ?? '',
|
||||
productId: original.productId,
|
||||
chatId: original.to,
|
||||
userId: original.userId,
|
||||
});
|
||||
return { success: result.success, messageId: result.messageId, error: result.error };
|
||||
}
|
||||
|
||||
if (original.channel === 'slack') {
|
||||
const result = await dispatchSlack({
|
||||
text: (original.metadata as Record<string, string>)?.text ?? original.subject ?? '',
|
||||
productId: original.productId,
|
||||
channel: original.to,
|
||||
userId: original.userId,
|
||||
});
|
||||
return { success: result.success, messageId: result.messageId, error: result.error };
|
||||
}
|
||||
|
||||
throw new BadRequestError(`Retry not supported for channel '${original.channel}'`);
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user