@orion-js/dogs 4.6.5 → 4.6.7

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/index.js CHANGED
@@ -177,7 +177,8 @@ __runInitializers(_init, 1, JobsHistoryRepo);
177
177
  // src/repos/JobsRepo.ts
178
178
  import { generateId } from "@orion-js/helpers";
179
179
  import { logger } from "@orion-js/logger";
180
- import { MongoCollection as MongoCollection2, Repository as Repository2 } from "@orion-js/mongodb";
180
+ import { MongoCollection as MongoCollection2, MongoDB as MongoDB2, Repository as Repository2 } from "@orion-js/mongodb";
181
+ import { clean, validate } from "@orion-js/schema";
181
182
 
182
183
  // src/services/partitions.ts
183
184
  function validatePartitionsCount(nPartitions) {
@@ -617,13 +618,13 @@ var JobsRepo = class {
617
618
  if (jobs.length === 0) {
618
619
  return { scheduledCount: 0, skippedCount: 0, errors: [] };
619
620
  }
620
- let scheduledCount = 0;
621
- let skippedCount = 0;
622
621
  const errors = [];
622
+ const preparedJobs = [];
623
623
  for (let i = 0; i < jobs.length; i++) {
624
624
  const job = jobs[i];
625
625
  try {
626
- await this.jobs.insertOne({
626
+ const record = await clean(JobRecordSchema, {
627
+ _id: this.jobs.generateId(),
627
628
  jobName: job.name,
628
629
  uniqueIdentifier: job.uniqueIdentifier,
629
630
  params: job.params,
@@ -632,16 +633,60 @@ var JobsRepo = class {
632
633
  type: "event",
633
634
  ...job.partition === void 0 ? {} : { partition: job.partition }
634
635
  });
635
- scheduledCount++;
636
+ await validate(JobRecordSchema, record);
637
+ preparedJobs.push({ index: i, job, record });
636
638
  } catch (error) {
637
- if (error.isValidationError && Object.values(error.validationErrors).includes("notUnique") && job.uniqueIdentifier) {
638
- logger.info(`Job "${job.name}" with identifier "${job.uniqueIdentifier}" already exists`);
639
- skippedCount++;
640
- } else {
639
+ errors.push({
640
+ index: i,
641
+ error: error instanceof Error ? error : new Error(String(error)),
642
+ job
643
+ });
644
+ }
645
+ }
646
+ if (preparedJobs.length === 0) {
647
+ return { scheduledCount: 0, skippedCount: 0, errors };
648
+ }
649
+ const rawCollection = await this.jobs.getRawCollection();
650
+ await this.jobs.createIndexesPromise;
651
+ const operations = preparedJobs.map(
652
+ ({ record }) => record.uniqueIdentifier === void 0 ? { insertOne: { document: record } } : {
653
+ updateOne: {
654
+ filter: { uniqueIdentifier: record.uniqueIdentifier },
655
+ update: { $setOnInsert: record },
656
+ upsert: true
657
+ }
658
+ }
659
+ );
660
+ let scheduledCount = 0;
661
+ let skippedCount = 0;
662
+ try {
663
+ const result = await rawCollection.bulkWrite(operations, { ordered: false });
664
+ scheduledCount = result.insertedCount + result.upsertedCount;
665
+ skippedCount = result.matchedCount;
666
+ } catch (error) {
667
+ const writeErrors = error instanceof MongoDB2.MongoBulkWriteError ? Array.isArray(error.writeErrors) ? error.writeErrors : [error.writeErrors] : [];
668
+ if (!(error instanceof MongoDB2.MongoBulkWriteError) || writeErrors.length === 0) {
669
+ for (const preparedJob of preparedJobs) {
641
670
  errors.push({
642
- index: i,
671
+ index: preparedJob.index,
643
672
  error: error instanceof Error ? error : new Error(String(error)),
644
- job
673
+ job: preparedJob.job
674
+ });
675
+ }
676
+ } else {
677
+ scheduledCount = error.result.insertedCount + error.result.upsertedCount;
678
+ skippedCount = error.result.matchedCount;
679
+ for (const writeError of writeErrors) {
680
+ const preparedJob = preparedJobs[writeError.index];
681
+ if (!preparedJob) continue;
682
+ if (writeError.code === 11e3 && preparedJob.record.uniqueIdentifier !== void 0) {
683
+ skippedCount++;
684
+ continue;
685
+ }
686
+ errors.push({
687
+ index: preparedJob.index,
688
+ error: new Error(writeError.errmsg),
689
+ job: preparedJob.job
645
690
  });
646
691
  }
647
692
  }
@@ -805,39 +850,102 @@ var Executor = class {
805
850
  return job.lockTime ?? jobToRun.lockTime;
806
851
  }
807
852
  getContext(job, jobToRun, onStale, isExecutionActive) {
808
- var _a;
809
853
  const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun);
810
- let staleTimeout = setTimeout(() => onStale(), effectiveLockTime);
811
- (_a = staleTimeout.unref) == null ? void 0 : _a.call(staleTimeout);
812
854
  const contextLogger = logger3.addMetadata({
813
855
  jobName: jobToRun.name,
814
856
  jobId: jobToRun.jobId
815
857
  });
858
+ let staleTimeout;
859
+ let watchdogCleared = false;
860
+ let staleReported = false;
861
+ let pendingExtraTime;
862
+ let renewalRunning = false;
863
+ let renewalPromise;
864
+ const clearCurrentStaleTimeout = () => {
865
+ if (staleTimeout === void 0) return;
866
+ clearTimeout(staleTimeout);
867
+ staleTimeout = void 0;
868
+ };
869
+ const reportStale = () => {
870
+ if (staleReported) return;
871
+ staleReported = true;
872
+ watchdogCleared = true;
873
+ pendingExtraTime = void 0;
874
+ clearCurrentStaleTimeout();
875
+ onStale();
876
+ };
877
+ const armStaleTimeout = (lockedUntil) => {
878
+ var _a;
879
+ if (watchdogCleared || staleReported || !isExecutionActive()) return;
880
+ clearCurrentStaleTimeout();
881
+ staleTimeout = setTimeout(
882
+ () => {
883
+ staleTimeout = void 0;
884
+ reportStale();
885
+ },
886
+ Math.max(0, lockedUntil - Date.now())
887
+ );
888
+ (_a = staleTimeout.unref) == null ? void 0 : _a.call(staleTimeout);
889
+ };
890
+ const runRenewals = async () => {
891
+ try {
892
+ while (pendingExtraTime !== void 0) {
893
+ const extraTime = pendingExtraTime;
894
+ pendingExtraTime = void 0;
895
+ if (watchdogCleared || staleReported || !isExecutionActive()) {
896
+ clearCurrentStaleTimeout();
897
+ return;
898
+ }
899
+ clearCurrentStaleTimeout();
900
+ const lockedUntil = Date.now() + extraTime;
901
+ let didExtend = false;
902
+ try {
903
+ didExtend = await this.jobsRepo.extendLockTime(
904
+ jobToRun.jobId,
905
+ extraTime,
906
+ jobToRun.lockId
907
+ );
908
+ } catch (error) {
909
+ reportStale();
910
+ throw error;
911
+ }
912
+ if (!didExtend) {
913
+ reportStale();
914
+ return;
915
+ }
916
+ if (watchdogCleared || staleReported || !isExecutionActive()) {
917
+ pendingExtraTime = void 0;
918
+ clearCurrentStaleTimeout();
919
+ return;
920
+ }
921
+ armStaleTimeout(lockedUntil);
922
+ }
923
+ } finally {
924
+ renewalRunning = false;
925
+ renewalPromise = void 0;
926
+ }
927
+ };
928
+ armStaleTimeout(Date.now() + effectiveLockTime);
816
929
  return {
817
930
  definition: job,
818
931
  record: jobToRun,
819
932
  tries: jobToRun.tries || 0,
820
- clearStaleTimeout: () => clearTimeout(staleTimeout),
821
- extendLockTime: async (extraTime) => {
822
- var _a2;
823
- if (!isExecutionActive()) {
933
+ clearStaleTimeout: () => {
934
+ watchdogCleared = true;
935
+ pendingExtraTime = void 0;
936
+ clearCurrentStaleTimeout();
937
+ },
938
+ extendLockTime: (extraTime) => {
939
+ if (watchdogCleared || staleReported || !isExecutionActive()) {
824
940
  contextLogger.warn(`Will not extend lock for stale execution "${jobToRun.executionId}"`);
825
- return;
826
- }
827
- clearTimeout(staleTimeout);
828
- let didExtend = false;
829
- try {
830
- didExtend = await this.jobsRepo.extendLockTime(jobToRun.jobId, extraTime, jobToRun.lockId);
831
- } catch (error) {
832
- onStale();
833
- throw error;
941
+ return Promise.resolve();
834
942
  }
835
- if (!didExtend) {
836
- onStale();
837
- return;
943
+ pendingExtraTime = Math.max(pendingExtraTime ?? extraTime, extraTime);
944
+ if (!renewalRunning) {
945
+ renewalRunning = true;
946
+ renewalPromise = runRenewals();
838
947
  }
839
- staleTimeout = setTimeout(() => onStale(), extraTime);
840
- (_a2 = staleTimeout.unref) == null ? void 0 : _a2.call(staleTimeout);
948
+ return renewalPromise ?? Promise.resolve();
841
949
  },
842
950
  logger: contextLogger
843
951
  };