@nmakarov/cli-toolkit 0.61.0 → 0.65.0

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.
package/dist/tasks.js CHANGED
@@ -463,6 +463,34 @@ async function updateTaskProgress(context, tasksTable, taskId, progress) {
463
463
  progress: typeof progress === "string" ? progress : JSON.stringify(progress)
464
464
  });
465
465
  }
466
+ function createTaskProgressReporter(context, tasksTable, taskId) {
467
+ let pump = null;
468
+ let pending = void 0;
469
+ let hasPending = false;
470
+ return (progress) => {
471
+ pending = progress;
472
+ hasPending = true;
473
+ if (pump) return pump;
474
+ pump = (async () => {
475
+ try {
476
+ while (hasPending) {
477
+ hasPending = false;
478
+ const value = pending;
479
+ try {
480
+ await updateTaskProgress(context, tasksTable, taskId, value);
481
+ } catch (err) {
482
+ context.logger?.warn?.(
483
+ `[tasks] progress update failed for ${taskId}: ${err?.message ?? err}`
484
+ );
485
+ }
486
+ }
487
+ } finally {
488
+ pump = null;
489
+ }
490
+ })();
491
+ return pump;
492
+ };
493
+ }
466
494
 
467
495
  // src/tasks/servicesRegistry.js
468
496
  function getDb2(context) {
@@ -876,8 +904,13 @@ var FileDatabase = class _FileDatabase {
876
904
  this.currentVersionFolder = await ensurePath(this.getDestinationPath(), version);
877
905
  }
878
906
  /**
879
- * Create a new version folder with comprehensive timestamp logic
880
- * Only works in versioned mode
907
+ * Create a new version folder named with the current UTC second.
908
+ * Only works in versioned mode.
909
+ *
910
+ * Clash protection: if that name already exists (two writers in the same
911
+ * second, or wall clock behind the latest version), advance +1s until free.
912
+ * Do NOT always derive from max(existing)+1s — that made successive harvests
913
+ * hours apart still land one second apart on disk.
881
914
  */
882
915
  async makeNewVersion() {
883
916
  if (!this.versioned) {
@@ -885,19 +918,22 @@ var FileDatabase = class _FileDatabase {
885
918
  }
886
919
  this.metadata = this.getDefaultMetadata();
887
920
  const existingVersions = await this.getVersions();
888
- let versionName;
921
+ const existingSet = new Set(existingVersions);
922
+ let candidateMs = Date.now();
889
923
  if (existingVersions.length > 0) {
890
- const maxTimestamp = existingVersions.reduce((max, version) => {
891
- const versionDate = new Date(version.replace("Z", ""));
892
- const maxDate2 = new Date(max.replace("Z", ""));
893
- return versionDate > maxDate2 ? version : max;
894
- });
895
- const maxDate = new Date(maxTimestamp.replace("Z", ""));
896
- const nextDate = new Date(maxDate.getTime() + 1e3);
897
- versionName = nextDate.toISOString().split(".")[0] + "Z";
898
- } else {
899
- const now = /* @__PURE__ */ new Date();
900
- versionName = now.toISOString().split(".")[0] + "Z";
924
+ let maxMs = 0;
925
+ for (const version of existingVersions) {
926
+ const ms = new Date(version).getTime();
927
+ if (Number.isFinite(ms) && ms > maxMs) maxMs = ms;
928
+ }
929
+ if (candidateMs <= maxMs) {
930
+ candidateMs = maxMs + 1e3;
931
+ }
932
+ }
933
+ let versionName = new Date(candidateMs).toISOString().split(".")[0] + "Z";
934
+ while (existingSet.has(versionName)) {
935
+ candidateMs += 1e3;
936
+ versionName = new Date(candidateMs).toISOString().split(".")[0] + "Z";
901
937
  }
902
938
  await this.setCurrentVersion(versionName);
903
939
  this.currentFileNumber = 0;
@@ -3376,7 +3412,8 @@ async function executeClaimedTask(context, tasksTable, historyTable, row, regist
3376
3412
  try {
3377
3413
  taskInstance = new TaskClass(context, row);
3378
3414
  runningTaskInstances.set(row.id, taskInstance);
3379
- const runResult = await taskInstance.run((progress) => updateTaskProgress(context, tasksTable, row.id, progress));
3415
+ const reportProgress = createTaskProgressReporter(context, tasksTable, row.id);
3416
+ const runResult = await taskInstance.run(reportProgress);
3380
3417
  success = !!runResult?.success;
3381
3418
  results = runResult?.results ?? null;
3382
3419
  } catch (error) {
@@ -3888,6 +3925,7 @@ export {
3888
3925
  coerceRuntimeValue,
3889
3926
  controlLaneTaskNames,
3890
3927
  convertPattern,
3928
+ createTaskProgressReporter,
3891
3929
  defaultTasksRegistry,
3892
3930
  enqueueStopTask,
3893
3931
  enqueueTask,