feat(msg): 修复通知服务并添加ES降级与Push Gateway推送

database.ts 导出db常量替代getDb()函数

env.ts JWT_SECRET/ES_URL改optional加DEV_MODE/PUSH_GATEWAY_URL

elasticsearch.ts ES降级: ES_URL未设置时esClient=null

notifications.service.ts 加createBatch+分页查询+Push Gateway推送调用

新建msg-init.sql创建2张表
This commit is contained in:
SpecialX
2026-07-09 09:08:57 +08:00
parent 421edd8a41
commit 416e1bc0b2
14 changed files with 498 additions and 207 deletions

View File

@@ -1,7 +1,12 @@
import { Catch, ExceptionFilter, ArgumentsHost, HttpException, Logger } from '@nestjs/common';
import { Request, Response } from 'express';
import { ZodError } from 'zod';
import { ApplicationError } from './application-error.js';
import {
Catch,
ExceptionFilter,
ArgumentsHost,
HttpException,
Logger,
} from "@nestjs/common";
import { ZodError } from "zod";
import { ApplicationError } from "./application-error.js";
@Catch()
export class GlobalErrorFilter implements ExceptionFilter {
@@ -9,10 +14,13 @@ export class GlobalErrorFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost): void {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
// NestJS HttpArgumentsHost 的 getResponse/getRequest 返回 express 实例,
// 但 msg 服务未引入 @types/express此处按 core-edu / content 模式不显式标注类型。
const response = ctx.getResponse();
const request = ctx.getRequest();
const traceId = (request.headers['x-request-id'] as string | undefined) ?? 'unknown';
const traceId =
(request.headers["x-request-id"] as string | undefined) ?? "unknown";
let statusCode = 500;
let body: Record<string, unknown>;
@@ -27,8 +35,8 @@ export class GlobalErrorFilter implements ExceptionFilter {
body = {
success: false,
error: {
code: 'MSG_VALIDATION_ERROR',
message: 'Validation failed',
code: "MSG_VALIDATION_ERROR",
message: "Validation failed",
details: exception.flatten(),
traceId,
},
@@ -40,7 +48,7 @@ export class GlobalErrorFilter implements ExceptionFilter {
body = {
success: false,
error: {
code: 'HTTP_ERROR',
code: "HTTP_ERROR",
message,
traceId,
},
@@ -53,8 +61,8 @@ export class GlobalErrorFilter implements ExceptionFilter {
body = {
success: false,
error: {
code: 'INTERNAL_ERROR',
message: 'An unexpected error occurred',
code: "INTERNAL_ERROR",
message: "An unexpected error occurred",
traceId,
},
};
@@ -63,14 +71,17 @@ export class GlobalErrorFilter implements ExceptionFilter {
response.status(statusCode).json(body);
}
private extractHttpMessage(res: string | object, exception: HttpException): string {
if (typeof res === 'string') {
private extractHttpMessage(
res: string | object,
exception: HttpException,
): string {
if (typeof res === "string") {
return res;
}
if (res && typeof res === 'object' && 'message' in res) {
if (res && typeof res === "object" && "message" in res) {
// 从 HttpException 响应体收窄类型NestJS 约定包含 message 字段)
const msg = (res as { message: unknown }).message;
return typeof msg === 'string' ? msg : exception.message;
return typeof msg === "string" ? msg : exception.message;
}
return exception.message;
}