feat: wire up notification system in server
This commit is contained in:
+74
-2
@@ -8,6 +8,15 @@ import path from 'node:path'
|
||||
import { ensureAdminUser } from './lib/bootstrap-admin.js'
|
||||
import { getOrCreateUnspecifiedCategory } from './lib/default-category.js'
|
||||
import { getMaxUploadBodyBytes, getProductImageMaxFileBytes } from './lib/upload-limits.js'
|
||||
import { createEventBus } from './lib/notifications/event-bus.js'
|
||||
import { createNotificationQueue } from './lib/notifications/queue.js'
|
||||
import { prisma } from './lib/prisma.js'
|
||||
import {
|
||||
resolveUserNotificationTargets,
|
||||
resolveAdminNotificationTargets,
|
||||
resolveAuthCodeTargets,
|
||||
} from './lib/notifications/preferences.js'
|
||||
import { NOTIFICATION_EVENTS, NOTIFICATION_CHANNELS } from './shared/constants/notification-events.js'
|
||||
import { registerAuth } from './plugins/auth.js'
|
||||
import { registerApiRoutes } from './routes/api.js'
|
||||
import { registerAuthRoutes } from './routes/auth.js'
|
||||
@@ -16,6 +25,7 @@ import { registerUserCartRoutes } from './routes/user-cart.js'
|
||||
import { registerUserMessageRoutes } from './routes/user-messages.js'
|
||||
import { registerUserOrderRoutes } from './routes/user-orders.js'
|
||||
import { registerUserPaymentRoutes } from './routes/user-payments.js'
|
||||
import { registerUserNotificationRoutes } from './routes/user/notifications.js'
|
||||
import { registerOAuthSocialRoutes } from './routes/oauth-social.js'
|
||||
import { registerUploadsResized } from './routes/uploads-resized.js'
|
||||
|
||||
@@ -42,7 +52,6 @@ await fastify.register(jwt, {
|
||||
await fastify.register(multipart, {
|
||||
limits: {
|
||||
files: 10,
|
||||
/** Совпадает с лимитом одного файла для `POST /api/admin/gallery/upload` (галерея). */
|
||||
fileSize: getProductImageMaxFileBytes(),
|
||||
},
|
||||
})
|
||||
@@ -70,6 +79,11 @@ fastify.decorate('authenticate', async function authenticate(request, reply) {
|
||||
}
|
||||
})
|
||||
|
||||
const eventBus = createEventBus()
|
||||
const notificationQueue = createNotificationQueue()
|
||||
fastify.decorate('eventBus', eventBus)
|
||||
fastify.decorate('notificationQueue', notificationQueue)
|
||||
|
||||
registerAuth(fastify)
|
||||
await registerAuthRoutes(fastify)
|
||||
await registerUserAddressRoutes(fastify)
|
||||
@@ -77,12 +91,70 @@ await registerUserCartRoutes(fastify)
|
||||
await registerUserMessageRoutes(fastify)
|
||||
await registerUserOrderRoutes(fastify)
|
||||
await registerUserPaymentRoutes(fastify)
|
||||
await registerUserNotificationRoutes(fastify)
|
||||
await registerOAuthSocialRoutes(fastify)
|
||||
await registerApiRoutes(fastify)
|
||||
await ensureAdminUser()
|
||||
await getOrCreateUnspecifiedCategory()
|
||||
|
||||
fastify.get('/health', async () => ({ ok: true }))
|
||||
await notificationQueue.flushPendingOnStartup()
|
||||
notificationQueue.start()
|
||||
|
||||
const {
|
||||
ORDER_CREATED,
|
||||
ORDER_STATUS_CHANGED,
|
||||
ORDER_MESSAGE_SENT,
|
||||
ORDER_MESSAGE_ADMIN_REPLY,
|
||||
PAYMENT_STATUS_CHANGED,
|
||||
AUTH_CODE_REQUESTED,
|
||||
} = NOTIFICATION_EVENTS
|
||||
|
||||
async function dispatchNotification(eventType, payload) {
|
||||
const userTargets = await resolveUserNotificationTargets(eventType, payload)
|
||||
for (const target of userTargets) {
|
||||
const log = await prisma.notificationLog.create({
|
||||
data: {
|
||||
userId: payload.userId,
|
||||
eventType,
|
||||
channel: target.channel,
|
||||
status: 'pending',
|
||||
payload: JSON.stringify(payload),
|
||||
},
|
||||
})
|
||||
notificationQueue.enqueue({ ...target, eventType, payload, logId: log.id })
|
||||
}
|
||||
|
||||
const adminEventType = eventType === 'order:created:admin' ? ORDER_CREATED : eventType
|
||||
const adminTargets = await resolveAdminNotificationTargets(adminEventType, payload)
|
||||
for (const target of adminTargets) {
|
||||
const log = await prisma.notificationLog.create({
|
||||
data: {
|
||||
eventType,
|
||||
channel: target.channel,
|
||||
status: 'pending',
|
||||
payload: JSON.stringify(payload),
|
||||
},
|
||||
})
|
||||
notificationQueue.enqueue({ ...target, eventType, payload, logId: log.id })
|
||||
}
|
||||
}
|
||||
|
||||
eventBus.on(ORDER_CREATED, dispatchNotification)
|
||||
eventBus.on(ORDER_STATUS_CHANGED, dispatchNotification)
|
||||
eventBus.on(ORDER_MESSAGE_SENT, dispatchNotification)
|
||||
eventBus.on(ORDER_MESSAGE_ADMIN_REPLY, dispatchNotification)
|
||||
eventBus.on(PAYMENT_STATUS_CHANGED, dispatchNotification)
|
||||
eventBus.on(AUTH_CODE_REQUESTED, dispatchNotification)
|
||||
eventBus.on('order:created:admin', dispatchNotification)
|
||||
eventBus.on('review:created', dispatchNotification)
|
||||
|
||||
async function shutdown() {
|
||||
notificationQueue.stop()
|
||||
await fastify.close()
|
||||
process.exit(0)
|
||||
}
|
||||
process.on('SIGINT', shutdown)
|
||||
process.on('SIGTERM', shutdown)
|
||||
|
||||
try {
|
||||
await fastify.listen({ port, host: '0.0.0.0' })
|
||||
|
||||
Reference in New Issue
Block a user