@steedos-labs/plugin-workflow 3.0.62 → 3.0.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4391,8 +4391,17 @@ UUFlowManager.timeoutAutoSubmit = async function (ins_id) {
4391
4391
  query._id = ins_id;
4392
4392
  }
4393
4393
 
4394
+ const startTime = Date.now();
4395
+ console.log(`[timeout_auto_submit] Starting timeout check with query:`, JSON.stringify(query));
4396
+
4394
4397
  const instances = await db.instances.find(query).toArray();
4395
4398
 
4399
+ console.log(`[timeout_auto_submit] Found ${instances.length} instance(s) matching timeout criteria`);
4400
+ if (instances.length > 0) {
4401
+ const instanceIds = instances.map(i => i._id).join(', ');
4402
+ console.log(`[timeout_auto_submit] Instance IDs: [${instanceIds}]`);
4403
+ }
4404
+
4396
4405
  for (const ins of instances) {
4397
4406
  try {
4398
4407
  const flow_id = ins.flow;
@@ -4401,6 +4410,7 @@ UUFlowManager.timeoutAutoSubmit = async function (ins_id) {
4401
4410
 
4402
4411
  // Only process if trace is not finished and due_date has passed
4403
4412
  if (trace.is_finished || !trace.due_date || new Date(trace.due_date) > new Date()) {
4413
+ console.log(`[timeout_auto_submit] Skipping instance ${instance_id}: trace finished=${trace.is_finished}, due_date=${trace.due_date}, now=${new Date()}`);
4404
4414
  continue;
4405
4415
  }
4406
4416
 
@@ -4431,8 +4441,21 @@ UUFlowManager.timeoutAutoSubmit = async function (ins_id) {
4431
4441
 
4432
4442
  // Process each unfinished approve in the trace sequentially to avoid race conditions
4433
4443
  const unfinishedApproves = trace.approves.filter(a => !a.is_finished);
4444
+ console.log(`[timeout_auto_submit] Instance ${instance_id}: Processing ${unfinishedApproves.length} unfinished approve(s) | flow=${flow_id} | step=${trace.step} | type=${step_type}`);
4445
+
4446
+ let successCount = 0;
4447
+ let failureCount_approves = 0;
4448
+ let skipCount = 0;
4434
4449
  for (const a of unfinishedApproves) {
4435
4450
  try {
4451
+ // Check failure count for this approve
4452
+ const failureCount = a.timeout_auto_submit_failures || 0;
4453
+ if (failureCount >= 3) {
4454
+ console.log(`[timeout_auto_submit] Skipping approve ${a._id} - exceeded max failures (count=${failureCount}), instance: ${instance_id}`);
4455
+ skipCount++;
4456
+ continue;
4457
+ }
4458
+
4436
4459
  // Create a separate approve_from_client for each approve to avoid shared mutation
4437
4460
  const approve_from_client = {
4438
4461
  _id: a._id,
@@ -4455,31 +4478,62 @@ UUFlowManager.timeoutAutoSubmit = async function (ins_id) {
4455
4478
  continue;
4456
4479
  }
4457
4480
 
4458
- console.log(`[timeout_auto_submit] Processing approve ${a._id} for instance ${instance_id}`);
4481
+ console.log(`[timeout_auto_submit] Processing approve ${a._id} for instance ${instance_id} (failure_count=${failureCount})`);
4459
4482
  console.log(`[timeout_auto_submit] current_user_info: ${JSON.stringify(current_user_info)}`);
4460
4483
 
4461
4484
  const updatedInstance = await UUFlowManager.workflow_engine(
4462
- approve_from_client,
4463
- current_user_info,
4464
- current_user_info._id,
4485
+ approve_from_client,
4486
+ current_user_info,
4487
+ current_user_info._id,
4465
4488
  true
4466
4489
  );
4467
4490
 
4468
4491
  await pushManager.send_instance_notification(
4469
- "auto_submit_pending_inbox",
4470
- updatedInstance,
4471
- "",
4492
+ "auto_submit_pending_inbox",
4493
+ updatedInstance,
4494
+ "",
4472
4495
  current_user_info
4473
4496
  );
4497
+ successCount++;
4474
4498
  } catch (approveError) {
4475
- console.error(`[timeout_auto_submit] Error processing approve ${a._id} for instance ${instance_id}: `, approveError.stack);
4499
+ const failureCount = (a.timeout_auto_submit_failures || 0) + 1;
4500
+ console.error(`[timeout_auto_submit] Error processing approve ${a._id} for instance ${instance_id} (failure_count=${failureCount}): ${approveError.message || approveError}`);
4501
+
4502
+ // Update the failure count in the database
4503
+ try {
4504
+ await db.instances.updateOne(
4505
+ {
4506
+ _id: instance_id,
4507
+ "traces._id": trace._id
4508
+ },
4509
+ {
4510
+ $set: {
4511
+ "traces.$[trace].approves.$[approve].timeout_auto_submit_failures": failureCount
4512
+ }
4513
+ },
4514
+ {
4515
+ arrayFilters: [
4516
+ { "trace._id": trace._id },
4517
+ { "approve._id": a._id }
4518
+ ]
4519
+ }
4520
+ );
4521
+ console.log(`[timeout_auto_submit] Updated failure count for approve ${a._id}: ${failureCount}`);
4522
+ } catch (updateError) {
4523
+ console.error(`[timeout_auto_submit] Failed to update failure count for approve ${a._id}: `, updateError.message || updateError);
4524
+ }
4525
+ failureCount_approves++;
4476
4526
  }
4477
4527
  }
4528
+ console.log(`[timeout_auto_submit] Instance ${instance_id} completed: success=${successCount} | failed=${failureCount_approves} | skipped=${skipCount}`);
4478
4529
  } catch (error) {
4479
4530
  console.error(`[timeout_auto_submit] Error processing instance ${ins._id}: `, error.stack);
4480
4531
  }
4481
4532
  }
4482
4533
 
4534
+ const duration = Date.now() - startTime;
4535
+ console.log(`[timeout_auto_submit] Completed processing ${instances.length} instance(s) in ${duration}ms`);
4536
+
4483
4537
  return true;
4484
4538
  };
4485
4539
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos-labs/plugin-workflow",
3
- "version": "3.0.62",
3
+ "version": "3.0.63",
4
4
  "main": "package.service.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -484,9 +484,19 @@ InstanceRecordQueue.Configure = function (options) {
484
484
  }
485
485
 
486
486
  // Universal send function
487
- var _querySend = function (doc) {
487
+ var _querySend = async function (doc) {
488
+ console.log(`[InstanceRecordQueue._querySend] 开始调用 sendDoc: docId=${doc._id}, insId=${doc.info.instance_id}`);
488
489
  if (InstanceRecordQueue.sendDoc) {
489
- InstanceRecordQueue.sendDoc(doc);
490
+ try {
491
+ await InstanceRecordQueue.sendDoc(doc);
492
+ console.log(`[InstanceRecordQueue._querySend] sendDoc 执行完成: docId=${doc._id}`);
493
+ } catch (error) {
494
+ console.error(`[InstanceRecordQueue._querySend] sendDoc 执行异常: docId=${doc._id}, error=${error.message}`);
495
+ console.error(`[InstanceRecordQueue._querySend] 错误堆栈: ${error.stack}`);
496
+ throw error;
497
+ }
498
+ } else {
499
+ console.warn(`[InstanceRecordQueue._querySend] InstanceRecordQueue.sendDoc 未定义! docId=${doc._id}`);
490
500
  }
491
501
 
492
502
  return {
@@ -494,18 +504,20 @@ InstanceRecordQueue.Configure = function (options) {
494
504
  };
495
505
  };
496
506
 
497
- self.serverSend = function (doc) {
507
+ self.serverSend = async function (doc) {
498
508
  doc = doc || {};
499
- return _querySend(doc);
509
+ return await _querySend(doc);
500
510
  };
501
511
 
502
512
  var isSendingDoc = false;
503
513
 
504
514
  if (options.sendInterval !== null) {
505
515
  var sendDoc = async function (doc) {
516
+ console.log(`[InstanceRecordQueue.sendDoc-queue] 处理队列文档: docId=${doc._id}, insId=${doc.info.instance_id}`);
506
517
  // Reserve doc
507
518
  var now = +new Date();
508
519
  var timeoutAt = now + options.sendTimeout;
520
+ console.log(`[InstanceRecordQueue.sendDoc-queue] 尝试 reserve 文档: docId=${doc._id}, now=${now}, timeoutAt=${timeoutAt}`);
509
521
  var reserved = await InstanceRecordQueue.collection.update({
510
522
  _id: doc._id,
511
523
  sent: false, // xxx: need to make sure this is set on create
@@ -520,16 +532,20 @@ InstanceRecordQueue.Configure = function (options) {
520
532
 
521
533
  // Make sure we only handle docs reserved by this instance
522
534
  if (reserved) {
535
+ console.log(`[InstanceRecordQueue.sendDoc-queue] 文档 reserve 成功: docId=${doc._id}, 开始调用 serverSend`);
523
536
  // Send
524
537
  var result = await self.serverSend(doc);
538
+ console.log(`[InstanceRecordQueue.sendDoc-queue] serverSend 返回结果: docId=${doc._id}, result=${JSON.stringify(result)}`);
525
539
 
526
540
  if (!options.keepDocs) {
527
541
  // Pr. Default we will remove docs
542
+ console.log(`[InstanceRecordQueue.sendDoc-queue] keepDocs=false, 删除文档: docId=${doc._id}`);
528
543
  await InstanceRecordQueue.collection.remove({
529
544
  _id: doc._id
530
545
  });
531
546
  } else {
532
547
  // Update
548
+ console.log(`[InstanceRecordQueue.sendDoc-queue] keepDocs=true, 设置 sent=true: docId=${doc._id}`);
533
549
  await InstanceRecordQueue.collection.update({
534
550
  _id: doc._id
535
551
  }, {
@@ -543,11 +559,15 @@ InstanceRecordQueue.Configure = function (options) {
543
559
  }
544
560
  });
545
561
  }
562
+ } else {
563
+ console.warn(`[InstanceRecordQueue.sendDoc-queue] 文档 reserve 失败(可能被其他实例处理): docId=${doc._id}`);
546
564
  } // Else could not reserve
547
565
  }; // EO sendDoc
548
566
 
549
567
  sendWorker(async function () {
568
+ console.log(`[InstanceRecordQueue.sendWorker] 定时器触发,开始处理待发送文档...`);
550
569
  if (isSendingDoc) {
570
+ console.log(`[InstanceRecordQueue.sendWorker] 上一次还在处理中,跳过本次轮询`);
551
571
  return;
552
572
  }
553
573
  // Set send fence
@@ -557,6 +577,7 @@ InstanceRecordQueue.Configure = function (options) {
557
577
 
558
578
  var now = +new Date();
559
579
 
580
+ console.log(`[InstanceRecordQueue.sendWorker] 查询待处理文档: batchSize=${batchSize}, now=${now}`);
560
581
  // Find docs that are not being or already sent
561
582
  var pendingDocs = await InstanceRecordQueue.collection.find({
562
583
  $and: [
@@ -584,10 +605,14 @@ InstanceRecordQueue.Configure = function (options) {
584
605
  },
585
606
  limit: batchSize
586
607
  }).toArray();
608
+ console.log(`[InstanceRecordQueue.sendWorker] 找到待处理文档数: ${pendingDocs.length}`);
609
+
587
610
  for (const doc of pendingDocs) {
588
611
  try {
612
+ console.log(`[InstanceRecordQueue.sendWorker] 处理文档: docId=${doc._id}, insId=${doc.info.instance_id}`);
589
613
  await sendDoc(doc);
590
614
  } catch (error) {
615
+ console.error(`[InstanceRecordQueue.sendWorker] 文档处理异常: docId=${doc._id}`);
591
616
  console.error(error.stack);
592
617
  console.log('InstanceRecordQueue: Could not send doc id: "' + doc._id + '", Error: ' + error.message);
593
618
  await InstanceRecordQueue.collection.update({
@@ -603,6 +628,7 @@ InstanceRecordQueue.Configure = function (options) {
603
628
 
604
629
  // Remove the send fence
605
630
  isSendingDoc = false;
631
+ console.log(`[InstanceRecordQueue.sendWorker] 本次轮询完成,已处理 ${pendingDocs.length} 个文档`);
606
632
  }, options.sendInterval || 15000); // Default every 15th sec
607
633
  } else {
608
634
  if (InstanceRecordQueue.debug) {
@@ -54,12 +54,16 @@ TimeoutAutoSubmit.Configure = function (options = {}) {
54
54
  return;
55
55
  }
56
56
  _isProcessing = true;
57
+ const startTime = Date.now();
57
58
  try {
58
- console.time('[timeout_auto_submit] execution');
59
+ console.log('[timeout_auto_submit] Starting timeout auto-submit check...');
59
60
  await UUFlowManager.timeoutAutoSubmit();
60
- console.timeEnd('[timeout_auto_submit] execution');
61
+ const duration = Date.now() - startTime;
62
+ console.log(`[timeout_auto_submit] Completed in ${duration}ms`);
61
63
  } catch (error) {
62
- console.error('[timeout_auto_submit] Error during scheduled execution:', error.stack || error);
64
+ const duration = Date.now() - startTime;
65
+ console.error(`[timeout_auto_submit] Fatal error after ${duration}ms: ${error.message}`);
66
+ console.error('[timeout_auto_submit] Stack trace:', error.stack);
63
67
  } finally {
64
68
  _isProcessing = false;
65
69
  }