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:
saravanakumardb1 2026-03-21 23:21:58 -07:00
parent f92504ceb4
commit 9180954903
3 changed files with 44 additions and 20 deletions

View File

@ -24,6 +24,7 @@ import {
interface DeliveryEntry { interface DeliveryEntry {
id: string; id: string;
pk: string;
template: string; template: string;
recipient: string; recipient: string;
channel: string; channel: string;
@ -71,8 +72,10 @@ export default function DeliveryPage() {
void loadData(); void loadData();
}, [loadData]); }, [loadData]);
async function handleRetry(id: string) { async function handleRetry(entry: DeliveryEntry) {
await apiFetch(`logs/${id}/retry`, { method: 'POST' }); await apiFetch(`logs/${entry.id}/retry?pk=${encodeURIComponent(entry.pk)}`, {
method: 'POST',
});
loadData(); loadData();
} }
@ -191,7 +194,7 @@ export default function DeliveryPage() {
<TableCell> <TableCell>
{e.status === 'failed' && ( {e.status === 'failed' && (
<button <button
onClick={() => handleRetry(e.id)} onClick={() => handleRetry(e)}
className="text-xs text-blue-600 hover:underline" className="text-xs text-blue-600 hover:underline"
> >
Retry Retry

View File

@ -81,21 +81,22 @@ export default function WebhooksPage() {
: []; : [];
setSubs(subsList); setSubs(subsList);
// Load deliveries per-subscription (backend only has GET /webhooks/subscriptions/:id/deliveries) // Load deliveries per-subscription in parallel (backend only has per-sub endpoint)
const allDeliveries: Delivery[] = []; const results = await Promise.allSettled(
for (const sub of subsList.slice(0, 10)) { subsList.slice(0, 10).map(sub =>
try { apiFetch(`subscriptions/${sub.id}/deliveries`).then((dData: Record<string, unknown>) => {
const dData = await apiFetch(`subscriptions/${sub.id}/deliveries`); const items: Delivery[] = Array.isArray(dData?.deliveries)
const items: Delivery[] = Array.isArray(dData?.deliveries) ? (dData.deliveries as Delivery[])
? dData.deliveries : Array.isArray(dData)
: Array.isArray(dData) ? (dData as unknown as Delivery[])
? dData : [];
: []; return items;
allDeliveries.push(...items); })
} catch { )
// best-effort );
} 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))); setDeliveries(allDeliveries.sort((a, b) => b.createdAt.localeCompare(a.createdAt)));
setLoading(false); setLoading(false);
}, []); }, []);

View File

@ -1,6 +1,6 @@
import type { FastifyInstance } from 'fastify'; import type { FastifyInstance } from 'fastify';
import { extractAuth } from '../../lib/auth.js'; import { extractAuth } from '../../lib/auth.js';
import { BadRequestError } from '../../lib/errors.js'; import { BadRequestError, NotFoundError } from '../../lib/errors.js';
import { import {
SendEmailSchema, SendEmailSchema,
SendSlackSchema, SendSlackSchema,
@ -130,7 +130,7 @@ export async function deliveryRoutes(app: FastifyInstance) {
// Look up the original log entry // Look up the original log entry
const original = await repo.getDeliveryLog(id, pk); 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') { if (original.status !== 'failed') {
throw new BadRequestError( throw new BadRequestError(
`Can only retry failed deliveries (current status: ${original.status})` `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 }; 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}'`); throw new BadRequestError(`Retry not supported for channel '${original.channel}'`);
}); });