Admin Notifications Integration
Admin Notifications Integration
This project now contains a standalone admin notification mechanism, but it is not wired into any business flow by default.
That means:
- The infrastructure is ready.
- No payment/auth/AI route will automatically send notifications.
- You decide where and when to call it.
What Is Included
The current implementation includes:
- A database-backed outbox for admin notification events and deliveries
- A dispatcher with retry support
- A Telegram channel implementation
- Admin settings for Telegram credentials and notification switches
- A protected dispatch route for cron or manual retry
Core files:
src/admin-notification/outbox.tssrc/admin-notification/dispatcher.tssrc/admin-notification/notifier.tssrc/admin-notification/channels/telegram.tssrc/app/api/admin-notifications/dispatch/route.ts
How It Works
The mechanism is designed to avoid slowing down your main business flow:
- Your code creates an admin notification event.
- The event is stored in the database outbox.
- Deliveries are created for enabled channels, such as Telegram.
- The dispatcher sends pending deliveries asynchronously.
- Failed deliveries are retried with backoff.
The intended model is:
- Main flow only enqueues
- Sending happens asynchronously
- Notification failure must not break the main business logic
Database Setup
This feature adds two new tables to the schema:
admin_notification_eventadmin_notification_delivery
Schema files:
src/config/db/schema.sqlite.tssrc/config/db/schema.postgres.tssrc/config/db/schema.mysql.ts
Apply the schema before using the feature:
pnpm run db:pushIf you use a migration-based workflow instead:
pnpm run db:generate
pnpm run db:migrateAdmin Settings
New settings are available in the admin panel under the Notifications tab.
Important keys:
admin_notification_enabledadmin_notification_order_enabledadmin_notification_alert_enabledadmin_notification_telegram_enabledadmin_notification_telegram_bot_tokenadmin_notification_telegram_chat_idsadmin_notification_telegram_thread_id
Recommended minimum configuration for Telegram:
- enable admin notifications
- enable Telegram channel
- provide bot token
- provide one or more chat IDs
admin_notification_telegram_chat_ids supports:
- one chat ID per line
- or comma-separated chat IDs
Manual Integration
Option 1: Use The Ready-Made Helper Methods
Import from:
import {
notifyAdminOrderPaid,
notifyAdminPaymentWebhookFailed,
notifyAdminSubscriptionCanceled,
notifyAdminSubscriptionRenewed,
} from '@/admin-notification';Example:
import { notifyAdminOrderPaid } from '@/admin-notification';
async function notifyOrder(order: {
orderNo: string;
amount?: number | null;
currency?: string | null;
paymentAmount?: number | null;
paymentCurrency?: string | null;
paymentProvider?: string | null;
paymentEmail?: string | null;
userEmail?: string | null;
productName?: string | null;
}) {
try {
await notifyAdminOrderPaid({
orderNo: order.orderNo,
amount: order.amount,
currency: order.currency,
paymentAmount: order.paymentAmount,
paymentCurrency: order.paymentCurrency,
paymentProvider: order.paymentProvider,
userEmail: order.paymentEmail || order.userEmail,
productName: order.productName,
});
} catch (error) {
console.log('enqueue admin notification failed', error);
}
}Use the same pattern for renew/cancel/alert helpers:
notifyAdminSubscriptionRenewednotifyAdminSubscriptionCancelednotifyAdminPaymentWebhookFailed
Option 2: Enqueue A Custom Admin Event
If your event does not match the built-in helpers, use the lower-level API:
import {
AdminNotificationEventType,
AdminNotificationLevel,
AdminNotificationSource,
enqueueAdminNotification,
} from '@/admin-notification';Example:
await enqueueAdminNotification({
eventType: AdminNotificationEventType.PAYMENT_WEBHOOK_FAILED,
level: AdminNotificationLevel.CRITICAL,
source: AdminNotificationSource.PAYMENT,
title: 'Custom webhook alert',
entityType: 'webhook',
entityId: 'stripe',
dedupeKey: `custom_webhook_alert:${Date.now()}`,
payload: {
provider: 'stripe',
error: 'custom error',
route: '/api/example',
occurredAt: new Date().toISOString(),
},
});If you need new event names, add them in:
src / admin - notification / types.ts;If you need a custom Telegram message layout, update:
src / admin - notification / templates / telegram.ts;Make Dispatch Near Real-Time
The built-in helper methods already call scheduleAdminNotificationDispatch().
If you use enqueueAdminNotification() directly and want immediate best-effort dispatch, call:
import {
enqueueAdminNotification,
scheduleAdminNotificationDispatch,
} from '@/admin-notification';
const result = await enqueueAdminNotification(...);
if (result.queued) {
scheduleAdminNotificationDispatch();
}This gives you:
- fast best-effort sending after the request lifecycle
- without blocking the main flow on Telegram API latency
Fallback Dispatch Route
There is a protected internal route:
/api/admin-notifications/dispatchIt requires:
Authorization: Bearer <AUTH_SECRET>
Example:
curl -X POST \
-H "Authorization: Bearer $AUTH_SECRET" \
"http://localhost:3000/api/admin-notifications/dispatch?limit=20"Use this route for:
- cron dispatch
- recovery after a failed async attempt
- manual operations
Cron Recommendation
Recommended fallback frequency:
- critical admin alerts: every
15sto30s - general admin notifications: every
30s
Suggested strategy:
- immediate best-effort dispatch from application code
- fallback cron for retry and recovery
Do not rely on high-frequency database polling alone unless you really need it.
Retry Rules
Current retry behavior is implemented in src/admin-notification/dispatcher.ts.
Backoff:
- 1st retry:
10s - 2nd retry:
30s - 3rd retry:
120s - later retries:
600s
Non-retryable cases should be treated as dead deliveries, for example:
- invalid credentials
- invalid chat ID
- unsupported channel
Telegram Setup
You need:
- A Telegram bot token from BotFather
- A destination chat ID
- Optionally a forum topic thread ID
Notes:
- group and channel chat IDs are usually negative numbers
- forum topics require
message_thread_id
If Telegram credentials are configured incorrectly, the main business flow should still continue, and only the delivery record should fail.
Recommended Integration Pattern
Use this structure whenever you wire notifications into business logic:
try {
await notifyAdminOrderPaid(...);
} catch (error) {
console.log('enqueue admin notification failed', error);
}Rules:
- do not let notification errors break the main business flow
- enqueue after your main business write succeeds
- do not
awaitTelegram API calls directly in business code - use the notifier or outbox layer only
Where To Integrate
Common integration points:
- payment success
- subscription renewal
- subscription cancellation
- webhook error handling
- AI callback failure
- storage provider failure
- signup / new user registration alerts
Keep the integration close to business success or failure boundaries, not inside UI code.
How To Test
- Configure Telegram settings in admin panel
- Ensure the database schema is applied
- Add one temporary manual call to a built-in notifier helper
- Trigger the corresponding flow
- Check the Telegram chat
- Check database rows in:
admin_notification_eventadmin_notification_delivery
- Trigger the dispatch route manually if needed
Current Limitations
Current V1 scope:
- admin notifications only
- Telegram channel only
- no built-in business auto-wiring
- no admin UI yet for listing deliveries
This is intentional. The current goal is to provide a stable mechanism that you can wire in selectively.
Suggested Next Steps
If you continue building this feature, the most useful next steps are:
- add an admin page for delivery status and dead-letter inspection
- move important event enqueue into the same DB transaction as the business write
- add more channels such as Slack, Email, or generic Webhook
- add more built-in notifier helpers for AI and system alerts