Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

129 lines
3.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Notion Sync Layer · 模块入口(完整实现)
* GH-GMP-005 · M1 · Agent搬迁工程
*
* GMP标准模块接口 · init/start/stop/healthCheck
* 对外暴露client, dbReader, pageRW, poller, cache
*/
'use strict';
const NotionSyncClient = require('./client');
const DBReader = require('./db-reader');
const PageRW = require('./page-rw');
const TicketPoller = require('./poller');
const TTLCache = require('./cache');
const MODULE_NAME = 'notion-sync';
const MODULE_VERSION = '1.0.0';
let client = null;
let dbReader = null;
let pageRW = null;
let poller = null;
let cache = null;
let logger = console;
module.exports = {
name: MODULE_NAME,
version: MODULE_VERSION,
type: 'service',
/**
* 初始化创建Notion客户端验证连接
*/
async init(context) {
logger = (context && context.logger) || console;
logger.info(`[${MODULE_NAME}] 初始化中 v${MODULE_VERSION}...`);
// 1. 创建客户端
client = new NotionSyncClient({ logger });
// 2. 验证Token有效性
const health = await client.healthCheck();
if (!health.ok) {
throw new Error(`[${MODULE_NAME}] Notion API连接失败: ${health.error}`);
}
logger.info(`[${MODULE_NAME}] Notion API连接成功 ✅`);
// 3. 读取工单数据库ID
const dbId = process.env.GH_NOTION_TICKET_DB_ID;
if (!dbId) {
throw new Error('[${MODULE_NAME}] GH_NOTION_TICKET_DB_ID 未配置');
}
// 4. 初始化子模块
cache = new TTLCache({ ttlMs: 10 * 60 * 1000, maxSize: 200 });
dbReader = new DBReader({ client, databaseId: dbId, logger });
pageRW = new PageRW({ client, logger });
logger.info(`[${MODULE_NAME}] 初始化完成 ✅ · DB: ${dbId.slice(0, 8)}...`);
return { status: 'ok', databaseId: dbId };
},
/**
* 启动轮询服务
* @param {object} context - 含 onNewTicket/onUpdatedTicket 回调
*/
async start(context) {
logger.info(`[${MODULE_NAME}] 启动同步服务...`);
const intervalMs = parseInt(process.env.AGENT_POLL_INTERVAL, 10) || 30000;
const stateDir = (context && context.dataDir) || process.cwd();
poller = new TicketPoller({
dbReader,
onNewTicket: (context && context.onNewTicket) || defaultNewTicketHandler,
onUpdatedTicket: (context && context.onUpdatedTicket) || null,
intervalMs,
stateDir,
logger,
});
poller.start();
logger.info(`[${MODULE_NAME}] 轮询已启动 · 间隔 ${intervalMs}ms`);
return { status: 'running', intervalMs };
},
async stop() {
logger.info(`[${MODULE_NAME}] 停止同步服务`);
if (poller) {
poller.stop();
poller = null;
}
if (cache) {
cache.clear();
}
return { status: 'stopped' };
},
async healthCheck() {
const clientHealth = client ? await client.healthCheck() : { ok: false, error: '未初始化' };
return {
status: clientHealth.ok ? 'ok' : 'error',
module: MODULE_NAME,
version: MODULE_VERSION,
notion: clientHealth,
poller: poller ? poller.stats : null,
cache: cache ? cache.stats : null,
};
},
// ─── 对外暴露子模块供agent-engine调用───
getClient: () => client,
getDBReader: () => dbReader,
getPageRW: () => pageRW,
getPoller: () => poller,
getCache: () => cache,
};
/**
* 默认新工单处理器仅日志实际由agent-engine覆盖
*/
async function defaultNewTicketHandler(ticket) {
logger.info(
`[${MODULE_NAME}] 检测到新工单 · ${ticket['编号'] || '无编号'} · ${ticket['任务标题']} · 等待agent-engine处理`
);
}