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:
@@ -1,13 +1,87 @@
|
||||
import { Client } from '@elastic/elasticsearch';
|
||||
import { env } from './env.js';
|
||||
import { Client } from "@elastic/elasticsearch";
|
||||
import { env } from "./env.js";
|
||||
|
||||
export const esClient = new Client({ node: env.ES_URL });
|
||||
/**
|
||||
* Elasticsearch 客户端。
|
||||
*
|
||||
* 降级模式:当 ES_URL 未设置或连接失败时,esClient 为 null,
|
||||
* 所有 ES 操作通过 safeIndex / safeSearch 自动跳过,服务仍可启动。
|
||||
*/
|
||||
export const esClient: Client | null = env.ES_URL
|
||||
? new Client({ node: env.ES_URL })
|
||||
: null;
|
||||
|
||||
/**
|
||||
* 探活 ES 连接。失败仅记录日志,不抛错(降级模式)。
|
||||
*/
|
||||
export async function checkEsConnection(): Promise<void> {
|
||||
if (!esClient) {
|
||||
console.log("Elasticsearch disabled (ES_URL not set)");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await esClient.ping();
|
||||
console.log('Elasticsearch connected');
|
||||
console.log("Elasticsearch connected");
|
||||
} catch (err) {
|
||||
console.error('Elasticsearch connection failed:', err);
|
||||
console.error("Elasticsearch connection failed:", err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭 ES 客户端连接。
|
||||
*/
|
||||
export async function closeEs(): Promise<void> {
|
||||
if (esClient) {
|
||||
await esClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
export interface IndexParams {
|
||||
index: string;
|
||||
id: string;
|
||||
document: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface SearchHit {
|
||||
_id: string;
|
||||
_source: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface SearchResult {
|
||||
hits: SearchHit[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全索引文档。client 为 null 或失败时跳过(降级模式),返回是否成功。
|
||||
*/
|
||||
export async function safeIndex(params: IndexParams): Promise<boolean> {
|
||||
if (!esClient) return false;
|
||||
try {
|
||||
await esClient.index(params);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error("Elasticsearch index failed:", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全搜索。client 为 null 或失败时返回空数组(降级模式)。
|
||||
*/
|
||||
export async function safeSearch(
|
||||
index: string,
|
||||
query: Record<string, unknown>,
|
||||
): Promise<SearchResult> {
|
||||
if (!esClient) return { hits: [] };
|
||||
try {
|
||||
const result = await esClient.search({ index, query });
|
||||
const hits = (result.hits.hits as unknown[]).map((raw) => {
|
||||
const hit = raw as { _id: string; _source: Record<string, unknown> };
|
||||
return { _id: hit._id, _source: hit._source };
|
||||
});
|
||||
return { hits };
|
||||
} catch (err) {
|
||||
console.error("Elasticsearch search failed:", err);
|
||||
return { hits: [] };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user