| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #!/usr/bin/env node
- /**
- * 修复调度器自动启动问题
- * 1. 修改PrintTriggerService,在创建延迟任务时自动启动调度器
- * 2. 修复时间计算使用数据库时间
- */
- const fs = require('fs');
- const path = require('path');
- console.log('=== 修复调度器自动启动问题 ===\n');
- // 1. 修复PrintTriggerService - 在handleOrderPaymentSuccess中自动启动调度器
- const printTriggerServicePath = path.join(__dirname, 'packages/feie-printer-module-mt/src/services/print-trigger.service.ts');
- console.log(`1. 修复 ${printTriggerServicePath}`);
- let printTriggerContent = fs.readFileSync(printTriggerServicePath, 'utf8');
- // 在handleOrderPaymentSuccess方法中添加调度器自动启动逻辑
- const searchPattern = `console.debug(\`[租户\${tenantId}] 订单支付成功打印任务已创建,订单ID: \${orderId}, 延迟时间: \${delaySeconds}秒\`);`;
- const replacement = `console.debug(\`[租户\${tenantId}] 订单支付成功打印任务已创建,订单ID: \${orderId}, 延迟时间: \${delaySeconds}秒\`);
- // 7. 自动启动调度器(如果未运行)
- try {
- console.debug(\`[租户\${tenantId}] 检查并启动延迟调度器...\`);
- const delaySchedulerService = new DelaySchedulerService(this.dataSource, this.feieConfig, tenantId);
- // 检查调度器状态
- const status = delaySchedulerService.getStatus();
- if (!status.isRunning) {
- await delaySchedulerService.start();
- console.debug(\`[租户\${tenantId}] 延迟调度器已启动\`);
- } else {
- console.debug(\`[租户\${tenantId}] 延迟调度器已在运行中\`);
- }
- // 立即处理一次任务(确保及时执行)
- const result = await delaySchedulerService.triggerManualProcess(tenantId);
- if (result.success) {
- console.debug(\`[租户\${tenantId}] 立即处理任务成功: \${result.message}\`);
- }
- } catch (error) {
- console.warn(\`[租户\${tenantId}] 启动调度器失败:\`, error);
- // 不抛出错误,避免影响主流程
- }`;
- if (printTriggerContent.includes(searchPattern)) {
- printTriggerContent = printTriggerContent.replace(searchPattern, replacement);
- fs.writeFileSync(printTriggerServicePath, printTriggerContent, 'utf8');
- console.log(' ✅ PrintTriggerService修复完成');
- } else {
- console.log(' ⚠️ 未找到匹配的代码,可能文件已修改');
- }
- // 2. 修复PrintTaskService - 使用数据库时间计算scheduledAt
- const printTaskServicePath = path.join(__dirname, 'packages/feie-printer-module-mt/src/services/print-task.service.ts');
- console.log(`\n2. 修复 ${printTaskServicePath}`);
- let printTaskContent = fs.readFileSync(printTaskServicePath, 'utf8');
- // 查找createPrintTask方法中的时间计算逻辑
- // 注意:这里使用字符串搜索,因为正则表达式在替换时有问题
- const timeReplacement = `// 计算计划打印时间
- let scheduledAt: Date | null = null;
- let printStatus = PrintStatus.DELAYED; // 所有通过此方法创建的任务都标记为DELAYED状态
- // 如果delaySeconds未定义或小于0,视为0
- const delaySeconds = taskDto.delaySeconds || 0;
- // 使用数据库时间计算计划时间,避免时间差异问题
- try {
- // 获取当前数据库时间
- const dbTimeResult = await this.dataSource.query('SELECT NOW() as db_time');
- const dbNow = new Date(dbTimeResult[0].db_time);
- if (delaySeconds >= 0) {
- scheduledAt = new Date(dbNow.getTime() + delaySeconds * 1000);
- } else {
- // 如果delaySeconds为负数,立即执行
- scheduledAt = dbNow;
- }
- } catch (error) {
- console.warn('获取数据库时间失败,使用本地时间:', error);
- // 回退到本地时间
- if (delaySeconds >= 0) {
- scheduledAt = new Date(Date.now() + delaySeconds * 1000);
- } else {
- scheduledAt = new Date();
- }
- }`;
- if (printTaskContent.includes('// 计算计划打印时间')) {
- // 使用更精确的替换
- const lines = printTaskContent.split('\n');
- let inTimeSection = false;
- let timeSectionStart = -1;
- let timeSectionEnd = -1;
- for (let i = 0; i < lines.length; i++) {
- if (lines[i].includes('// 计算计划打印时间')) {
- inTimeSection = true;
- timeSectionStart = i;
- }
- if (inTimeSection && lines[i].includes('scheduledAt = new Date(Date.now() + delaySeconds * 1000);')) {
- timeSectionEnd = i;
- break;
- }
- }
- if (timeSectionStart !== -1 && timeSectionEnd !== -1) {
- const before = lines.slice(0, timeSectionStart).join('\n');
- const after = lines.slice(timeSectionEnd + 1).join('\n');
- printTaskContent = before + '\n' + timeReplacement + '\n' + after;
- fs.writeFileSync(printTaskServicePath, printTaskContent, 'utf8');
- console.log(' ✅ PrintTaskService时间计算修复完成');
- } else {
- console.log(' ⚠️ 未找到时间计算代码,可能文件结构已变化');
- }
- } else {
- console.log(' ⚠️ 未找到时间计算注释');
- }
- // 3. 创建应用启动时自动启动调度器的脚本
- const autoStartScriptPath = path.join(__dirname, 'packages/feie-printer-module-mt/src/auto-start-scheduler.ts');
- console.log(`\n3. 创建自动启动脚本: ${autoStartScriptPath}`);
- const autoStartScript = `/**
- * 自动启动延迟调度器
- * 在应用启动时自动启动所有租户的延迟调度器
- */
- import { DataSource } from 'typeorm';
- import { DelaySchedulerService } from './services/delay-scheduler.service';
- import { FeieApiConfig } from './types/feie.types';
- export async function autoStartSchedulers(dataSource: DataSource): Promise<void> {
- console.log('=== 自动启动延迟调度器 ===');
- try {
- // 获取飞鹅API配置(简化版,实际应从配置服务获取)
- const feieConfig: FeieApiConfig = {
- baseUrl: 'https://api.feieyun.cn/Api/Open/',
- user: '',
- ukey: '',
- timeout: 10000,
- maxRetries: 3
- };
- // 获取所有有延迟任务的租户
- const tenantResults = await dataSource.query(\`
- SELECT DISTINCT tenant_id
- FROM feie_print_task_mt
- WHERE print_status IN ('DELAYED', 'PENDING')
- AND scheduled_at <= NOW() + INTERVAL '1 hour' -- 包括未来1小时内的任务
- ORDER BY tenant_id
- \`);
- const tenantIds = tenantResults.map((row: any) => row.tenant_id);
- if (tenantIds.length === 0) {
- console.log('没有找到需要调度器处理的租户');
- return;
- }
- console.log(\`找到 \${tenantIds.length} 个需要调度器的租户: \${tenantIds.join(', ')}\`);
- // 为每个租户启动调度器
- for (const tenantId of tenantIds) {
- try {
- const scheduler = new DelaySchedulerService(dataSource, feieConfig, tenantId);
- // 检查是否已运行
- const status = scheduler.getStatus();
- if (!status.isRunning) {
- await scheduler.start();
- console.log(\`租户 \${tenantId} 调度器已启动\`);
- } else {
- console.log(\`租户 \${tenantId} 调度器已在运行中\`);
- }
- // 立即处理一次积压任务
- const result = await scheduler.triggerManualProcess(tenantId);
- if (result.success && result.processedTasks > 0) {
- console.log(\`租户 \${tenantId} 处理了 \${result.processedTasks} 个积压任务\`);
- }
- } catch (error) {
- console.error(\`租户 \${tenantId} 调度器启动失败:\`, error);
- }
- }
- console.log('=== 延迟调度器自动启动完成 ===');
- } catch (error) {
- console.error('自动启动调度器失败:', error);
- }
- }`;
- fs.writeFileSync(autoStartScriptPath, autoStartScript, 'utf8');
- console.log(' ✅ 自动启动脚本创建完成');
- console.log('\n=== 修复完成 ===');
- console.log('\n下一步操作:');
- console.log('1. 重新构建飞鹅打印模块: pnpm build:feie');
- console.log('2. 重启应用服务');
- console.log('3. 检查调度器是否自动启动');
- console.log('4. 验证延迟任务是否被处理');
|