payload 4.0.0-internal.cd69eef → 4.0.0-internal.d1cc1d3

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.
Files changed (279) hide show
  1. package/dist/admin/RichText.d.ts +1 -1
  2. package/dist/admin/RichText.d.ts.map +1 -1
  3. package/dist/admin/RichText.js.map +1 -1
  4. package/dist/admin/functions/index.d.ts +10 -8
  5. package/dist/admin/functions/index.d.ts.map +1 -1
  6. package/dist/admin/functions/index.js.map +1 -1
  7. package/dist/admin/types.d.ts +2 -2
  8. package/dist/admin/types.d.ts.map +1 -1
  9. package/dist/admin/types.js.map +1 -1
  10. package/dist/auth/endpoints/login.d.ts.map +1 -1
  11. package/dist/auth/endpoints/login.js +2 -11
  12. package/dist/auth/endpoints/login.js.map +1 -1
  13. package/dist/auth/loginWithCookie.d.ts +33 -0
  14. package/dist/auth/loginWithCookie.d.ts.map +1 -0
  15. package/dist/auth/loginWithCookie.js +34 -0
  16. package/dist/auth/loginWithCookie.js.map +1 -0
  17. package/dist/auth/serverFunctions/cookies.d.ts +47 -0
  18. package/dist/auth/serverFunctions/cookies.d.ts.map +1 -0
  19. package/dist/auth/serverFunctions/cookies.js +52 -0
  20. package/dist/auth/serverFunctions/cookies.js.map +1 -0
  21. package/dist/auth/serverFunctions/login.d.ts +29 -0
  22. package/dist/auth/serverFunctions/login.d.ts.map +1 -0
  23. package/dist/auth/serverFunctions/login.js +63 -0
  24. package/dist/auth/serverFunctions/login.js.map +1 -0
  25. package/dist/auth/serverFunctions/logout.d.ts +17 -0
  26. package/dist/auth/serverFunctions/logout.d.ts.map +1 -0
  27. package/dist/auth/serverFunctions/logout.js +58 -0
  28. package/dist/auth/serverFunctions/logout.js.map +1 -0
  29. package/dist/auth/serverFunctions/refresh.d.ts +17 -0
  30. package/dist/auth/serverFunctions/refresh.d.ts.map +1 -0
  31. package/dist/auth/serverFunctions/refresh.js +61 -0
  32. package/dist/auth/serverFunctions/refresh.js.map +1 -0
  33. package/dist/collections/config/client.d.ts +2 -3
  34. package/dist/collections/config/client.d.ts.map +1 -1
  35. package/dist/collections/config/client.js +5 -7
  36. package/dist/collections/config/client.js.map +1 -1
  37. package/dist/collections/config/defaults.d.ts.map +1 -1
  38. package/dist/collections/config/defaults.js +1 -0
  39. package/dist/collections/config/defaults.js.map +1 -1
  40. package/dist/collections/config/sanitize.d.ts +3 -8
  41. package/dist/collections/config/sanitize.d.ts.map +1 -1
  42. package/dist/collections/config/sanitize.js +2 -6
  43. package/dist/collections/config/sanitize.js.map +1 -1
  44. package/dist/collections/config/types.d.ts +1 -1
  45. package/dist/collections/config/types.d.ts.map +1 -1
  46. package/dist/collections/config/types.js.map +1 -1
  47. package/dist/collections/config/useAsTitle.spec.js +27 -27
  48. package/dist/collections/config/useAsTitle.spec.js.map +1 -1
  49. package/dist/collections/operations/create.d.ts.map +1 -1
  50. package/dist/collections/operations/create.js +10 -0
  51. package/dist/collections/operations/create.js.map +1 -1
  52. package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
  53. package/dist/collections/operations/restoreVersion.js +7 -4
  54. package/dist/collections/operations/restoreVersion.js.map +1 -1
  55. package/dist/collections/operations/updateByID.js +1 -0
  56. package/dist/collections/operations/updateByID.js.map +1 -1
  57. package/dist/config/build.js +1 -1
  58. package/dist/config/build.js.map +1 -1
  59. package/dist/config/defaults.d.ts.map +1 -1
  60. package/dist/config/defaults.js +5 -2
  61. package/dist/config/defaults.js.map +1 -1
  62. package/dist/config/orderable/index.d.ts +1 -1
  63. package/dist/config/orderable/index.d.ts.map +1 -1
  64. package/dist/config/orderable/index.js +2 -2
  65. package/dist/config/orderable/index.js.map +1 -1
  66. package/dist/config/sanitize.d.ts +1 -1
  67. package/dist/config/sanitize.d.ts.map +1 -1
  68. package/dist/config/sanitize.js +33 -40
  69. package/dist/config/sanitize.js.map +1 -1
  70. package/dist/config/types.d.ts +1 -1
  71. package/dist/config/types.js.map +1 -1
  72. package/dist/database/createDatabaseAdapter.d.ts +1 -1
  73. package/dist/database/createDatabaseAdapter.d.ts.map +1 -1
  74. package/dist/database/createDatabaseAdapter.js +0 -2
  75. package/dist/database/createDatabaseAdapter.js.map +1 -1
  76. package/dist/database/types.d.ts +6 -0
  77. package/dist/database/types.d.ts.map +1 -1
  78. package/dist/database/types.js.map +1 -1
  79. package/dist/exports/auth.d.ts +5 -0
  80. package/dist/exports/auth.d.ts.map +1 -0
  81. package/dist/exports/auth.js +6 -0
  82. package/dist/exports/auth.js.map +1 -0
  83. package/dist/exports/internal.d.ts +2 -0
  84. package/dist/exports/internal.d.ts.map +1 -1
  85. package/dist/exports/internal.js +3 -1
  86. package/dist/exports/internal.js.map +1 -1
  87. package/dist/fields/baseFields/slug/duplicateContext.d.ts +11 -0
  88. package/dist/fields/baseFields/slug/duplicateContext.d.ts.map +1 -0
  89. package/dist/fields/baseFields/slug/duplicateContext.js +21 -0
  90. package/dist/fields/baseFields/slug/duplicateContext.js.map +1 -0
  91. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.d.ts +22 -0
  92. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.d.ts.map +1 -0
  93. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.js +63 -0
  94. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.js.map +1 -0
  95. package/dist/fields/baseFields/slug/generateSlug.d.ts +13 -8
  96. package/dist/fields/baseFields/slug/generateSlug.d.ts.map +1 -1
  97. package/dist/fields/baseFields/slug/generateSlug.js +98 -45
  98. package/dist/fields/baseFields/slug/generateSlug.js.map +1 -1
  99. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.d.ts +18 -0
  100. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.d.ts.map +1 -0
  101. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.js +20 -0
  102. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.js.map +1 -0
  103. package/dist/fields/baseFields/slug/getSlugFallbackValue.d.ts +22 -0
  104. package/dist/fields/baseFields/slug/getSlugFallbackValue.d.ts.map +1 -0
  105. package/dist/fields/baseFields/slug/getSlugFallbackValue.js +23 -0
  106. package/dist/fields/baseFields/slug/getSlugFallbackValue.js.map +1 -0
  107. package/dist/fields/baseFields/slug/hasValue.d.ts +3 -0
  108. package/dist/fields/baseFields/slug/hasValue.d.ts.map +1 -0
  109. package/dist/fields/baseFields/slug/hasValue.js +3 -0
  110. package/dist/fields/baseFields/slug/hasValue.js.map +1 -0
  111. package/dist/fields/config/reservedFieldNames.spec.js +18 -18
  112. package/dist/fields/config/reservedFieldNames.spec.js.map +1 -1
  113. package/dist/fields/config/sanitize.d.ts +3 -9
  114. package/dist/fields/config/sanitize.d.ts.map +1 -1
  115. package/dist/fields/config/sanitize.js +33 -34
  116. package/dist/fields/config/sanitize.js.map +1 -1
  117. package/dist/fields/config/sanitize.spec.js +128 -105
  118. package/dist/fields/config/sanitize.spec.js.map +1 -1
  119. package/dist/fields/config/types.d.ts +4 -3
  120. package/dist/fields/config/types.d.ts.map +1 -1
  121. package/dist/fields/config/types.js.map +1 -1
  122. package/dist/fields/hooks/beforeValidate/promise.d.ts.map +1 -1
  123. package/dist/fields/hooks/beforeValidate/promise.js +5 -3
  124. package/dist/fields/hooks/beforeValidate/promise.js.map +1 -1
  125. package/dist/fields/hooks/beforeValidate/stripNullRows.d.ts +10 -0
  126. package/dist/fields/hooks/beforeValidate/stripNullRows.d.ts.map +1 -0
  127. package/dist/fields/hooks/beforeValidate/stripNullRows.js +18 -0
  128. package/dist/fields/hooks/beforeValidate/stripNullRows.js.map +1 -0
  129. package/dist/fields/validations.d.ts.map +1 -1
  130. package/dist/fields/validations.js +7 -8
  131. package/dist/fields/validations.js.map +1 -1
  132. package/dist/fields/validations.spec.js +61 -37
  133. package/dist/fields/validations.spec.js.map +1 -1
  134. package/dist/globals/config/sanitize.d.ts +2 -7
  135. package/dist/globals/config/sanitize.d.ts.map +1 -1
  136. package/dist/globals/config/sanitize.js +2 -6
  137. package/dist/globals/config/sanitize.js.map +1 -1
  138. package/dist/globals/config/sanitize.spec.js +6 -6
  139. package/dist/globals/config/sanitize.spec.js.map +1 -1
  140. package/dist/globals/operations/countGlobalVersions.d.ts.map +1 -1
  141. package/dist/globals/operations/countGlobalVersions.js +1 -0
  142. package/dist/globals/operations/countGlobalVersions.js.map +1 -1
  143. package/dist/index.bundled.d.ts +247 -178
  144. package/dist/index.d.ts +49 -17
  145. package/dist/index.d.ts.map +1 -1
  146. package/dist/index.js +3 -0
  147. package/dist/index.js.map +1 -1
  148. package/dist/query-presets/constraints.js +1 -1
  149. package/dist/query-presets/constraints.js.map +1 -1
  150. package/dist/queues/config/collection.d.ts.map +1 -1
  151. package/dist/queues/config/collection.js +37 -43
  152. package/dist/queues/config/collection.js.map +1 -1
  153. package/dist/queues/config/global.d.ts +5 -6
  154. package/dist/queues/config/global.d.ts.map +1 -1
  155. package/dist/queues/config/global.js +1 -1
  156. package/dist/queues/config/global.js.map +1 -1
  157. package/dist/queues/config/types/index.d.ts +29 -24
  158. package/dist/queues/config/types/index.d.ts.map +1 -1
  159. package/dist/queues/config/types/index.js.map +1 -1
  160. package/dist/queues/config/types/taskTypes.d.ts +4 -7
  161. package/dist/queues/config/types/taskTypes.d.ts.map +1 -1
  162. package/dist/queues/config/types/taskTypes.js.map +1 -1
  163. package/dist/queues/config/types/workflowJSONTypes.d.ts +10 -9
  164. package/dist/queues/config/types/workflowJSONTypes.d.ts.map +1 -1
  165. package/dist/queues/config/types/workflowJSONTypes.js.map +1 -1
  166. package/dist/queues/config/types/workflowTypes.d.ts +11 -58
  167. package/dist/queues/config/types/workflowTypes.d.ts.map +1 -1
  168. package/dist/queues/config/types/workflowTypes.js.map +1 -1
  169. package/dist/queues/endpoints/handleSchedules.js +1 -1
  170. package/dist/queues/endpoints/handleSchedules.js.map +1 -1
  171. package/dist/queues/errors/handleTaskError.js +4 -4
  172. package/dist/queues/errors/handleTaskError.js.map +1 -1
  173. package/dist/queues/errors/handleWorkflowError.js +1 -1
  174. package/dist/queues/errors/handleWorkflowError.js.map +1 -1
  175. package/dist/queues/errors/index.d.ts +6 -0
  176. package/dist/queues/errors/index.d.ts.map +1 -1
  177. package/dist/queues/errors/index.js +5 -0
  178. package/dist/queues/errors/index.js.map +1 -1
  179. package/dist/queues/localAPI.d.ts +4 -4
  180. package/dist/queues/localAPI.d.ts.map +1 -1
  181. package/dist/queues/localAPI.js +63 -66
  182. package/dist/queues/localAPI.js.map +1 -1
  183. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts +4 -4
  184. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts.map +1 -1
  185. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.js.map +1 -1
  186. package/dist/queues/operations/handleSchedules/index.d.ts +1 -1
  187. package/dist/queues/operations/handleSchedules/index.d.ts.map +1 -1
  188. package/dist/queues/operations/handleSchedules/index.js +1 -1
  189. package/dist/queues/operations/handleSchedules/index.js.map +1 -1
  190. package/dist/queues/operations/runJobs/heartbeat.d.ts +13 -0
  191. package/dist/queues/operations/runJobs/heartbeat.d.ts.map +1 -0
  192. package/dist/queues/operations/runJobs/heartbeat.js +66 -0
  193. package/dist/queues/operations/runJobs/heartbeat.js.map +1 -0
  194. package/dist/queues/operations/runJobs/index.d.ts.map +1 -1
  195. package/dist/queues/operations/runJobs/index.js +133 -84
  196. package/dist/queues/operations/runJobs/index.js.map +1 -1
  197. package/dist/queues/operations/runJobs/runJSONJob/index.d.ts.map +1 -1
  198. package/dist/queues/operations/runJobs/runJSONJob/index.js +6 -3
  199. package/dist/queues/operations/runJobs/runJSONJob/index.js.map +1 -1
  200. package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js +5 -5
  201. package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js.map +1 -1
  202. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts +2 -1
  203. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts.map +1 -1
  204. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js +39 -8
  205. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js.map +1 -1
  206. package/dist/queues/operations/runJobs/runJob/importHandlerPath.js.map +1 -1
  207. package/dist/queues/operations/runJobs/runJob/index.d.ts.map +1 -1
  208. package/dist/queues/operations/runJobs/runJob/index.js +4 -4
  209. package/dist/queues/operations/runJobs/runJob/index.js.map +1 -1
  210. package/dist/queues/utilities/updateJob.d.ts.map +1 -1
  211. package/dist/queues/utilities/updateJob.js +3 -0
  212. package/dist/queues/utilities/updateJob.js.map +1 -1
  213. package/dist/types/index.d.ts +2 -2
  214. package/dist/types/index.d.ts.map +1 -1
  215. package/dist/types/index.js.map +1 -1
  216. package/dist/uploads/checkFileRestrictions.d.ts +1 -1
  217. package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
  218. package/dist/uploads/checkFileRestrictions.js +15 -1
  219. package/dist/uploads/checkFileRestrictions.js.map +1 -1
  220. package/dist/uploads/endpoints/uploadInstructions.d.ts +12 -0
  221. package/dist/uploads/endpoints/uploadInstructions.d.ts.map +1 -1
  222. package/dist/uploads/endpoints/uploadInstructions.js +66 -20
  223. package/dist/uploads/endpoints/uploadInstructions.js.map +1 -1
  224. package/dist/uploads/generateFileData.js +4 -1
  225. package/dist/uploads/generateFileData.js.map +1 -1
  226. package/dist/uploads/getFileFromUploadInstructions.d.ts +8 -0
  227. package/dist/uploads/getFileFromUploadInstructions.d.ts.map +1 -0
  228. package/dist/uploads/getFileFromUploadInstructions.js +62 -0
  229. package/dist/uploads/getFileFromUploadInstructions.js.map +1 -0
  230. package/dist/uploads/getImageSize.d.ts +12 -1
  231. package/dist/uploads/getImageSize.d.ts.map +1 -1
  232. package/dist/uploads/getImageSize.js +20 -18
  233. package/dist/uploads/getImageSize.js.map +1 -1
  234. package/dist/uploads/getImageSize.spec.js +298 -0
  235. package/dist/uploads/getImageSize.spec.js.map +1 -0
  236. package/dist/uploads/probeImageSize.d.ts +39 -0
  237. package/dist/uploads/probeImageSize.d.ts.map +1 -0
  238. package/dist/uploads/probeImageSize.js +374 -0
  239. package/dist/uploads/probeImageSize.js.map +1 -0
  240. package/dist/uploads/probeImageSize.spec.js +366 -0
  241. package/dist/uploads/probeImageSize.spec.js.map +1 -0
  242. package/dist/uploads/stagedUpload.d.ts +27 -0
  243. package/dist/uploads/stagedUpload.d.ts.map +1 -0
  244. package/dist/uploads/stagedUpload.js +197 -0
  245. package/dist/uploads/stagedUpload.js.map +1 -0
  246. package/dist/uploads/types.d.ts +41 -13
  247. package/dist/uploads/types.d.ts.map +1 -1
  248. package/dist/uploads/types.js.map +1 -1
  249. package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
  250. package/dist/utilities/addDataAndFileToRequest.js +12 -46
  251. package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
  252. package/dist/utilities/configToJSONSchema.spec.js +33 -33
  253. package/dist/utilities/configToJSONSchema.spec.js.map +1 -1
  254. package/dist/utilities/fieldValueExists.d.ts +29 -0
  255. package/dist/utilities/fieldValueExists.d.ts.map +1 -0
  256. package/dist/utilities/fieldValueExists.js +27 -0
  257. package/dist/utilities/fieldValueExists.js.map +1 -0
  258. package/dist/utilities/getUniqueFieldValue.d.ts +27 -0
  259. package/dist/utilities/getUniqueFieldValue.d.ts.map +1 -0
  260. package/dist/utilities/getUniqueFieldValue.js +26 -0
  261. package/dist/utilities/getUniqueFieldValue.js.map +1 -0
  262. package/dist/versions/deleteScheduledPublishJobs.js +2 -2
  263. package/dist/versions/deleteScheduledPublishJobs.js.map +1 -1
  264. package/dist/versions/payloadPackageList.d.ts.map +1 -1
  265. package/dist/versions/payloadPackageList.js +0 -1
  266. package/dist/versions/payloadPackageList.js.map +1 -1
  267. package/package.json +8 -3
  268. package/dist/database/defaultUpdateJobs.d.ts +0 -3
  269. package/dist/database/defaultUpdateJobs.d.ts.map +0 -1
  270. package/dist/database/defaultUpdateJobs.js +0 -41
  271. package/dist/database/defaultUpdateJobs.js.map +0 -1
  272. package/dist/fields/baseFields/slug/countVersions.d.ts +0 -13
  273. package/dist/fields/baseFields/slug/countVersions.d.ts.map +0 -1
  274. package/dist/fields/baseFields/slug/countVersions.js +0 -27
  275. package/dist/fields/baseFields/slug/countVersions.js.map +0 -1
  276. package/dist/uploads/tempFile.d.ts +0 -7
  277. package/dist/uploads/tempFile.d.ts.map +0 -1
  278. package/dist/uploads/tempFile.js +0 -39
  279. package/dist/uploads/tempFile.js.map +0 -1
@@ -1,9 +1,11 @@
1
+ import { v4 as uuid } from 'uuid';
1
2
  import { Forbidden } from '../../../errors/Forbidden.js';
2
3
  import { isolateObjectProperty } from '../../../utilities/isolateObjectProperty.js';
3
4
  import { jobsCollectionSlug } from '../../config/collection.js';
4
- import { JobCancelledError } from '../../errors/index.js';
5
+ import { JobCancelledError, JobRunAbortedError } from '../../errors/index.js';
5
6
  import { getCurrentDate } from '../../utilities/getCurrentDate.js';
6
- import { updateJob, updateJobs } from '../../utilities/updateJob.js';
7
+ import { updateJobs } from '../../utilities/updateJob.js';
8
+ import { startProcessingLeaseHeartbeat } from './heartbeat.js';
7
9
  import { getUpdateJobFunction } from './runJob/getUpdateJobFunction.js';
8
10
  import { importHandlerPath } from './runJob/importHandlerPath.js';
9
11
  import { runJob } from './runJob/index.js';
@@ -21,6 +23,11 @@ export const runJobs = async (args)=>{
21
23
  throw new Forbidden(req.t);
22
24
  }
23
25
  }
26
+ const now = getCurrentDate();
27
+ const { duration: processingLeaseDuration, safetyBuffer: processingLeaseSafetyBuffer } = jobsConfig.processingLease;
28
+ const nowISOString = now.toISOString();
29
+ const processingUntil = new Date(now.getTime() + processingLeaseDuration).toISOString();
30
+ const processingToken = uuid();
24
31
  const and = [
25
32
  {
26
33
  completedAt: {
@@ -33,9 +40,18 @@ export const runJobs = async (args)=>{
33
40
  }
34
41
  },
35
42
  {
36
- processing: {
37
- equals: false
38
- }
43
+ or: [
44
+ {
45
+ processingUntil: {
46
+ exists: false
47
+ }
48
+ },
49
+ {
50
+ processingUntil: {
51
+ less_than_equal: nowISOString
52
+ }
53
+ }
54
+ ]
39
55
  },
40
56
  {
41
57
  or: [
@@ -46,13 +62,13 @@ export const runJobs = async (args)=>{
46
62
  },
47
63
  {
48
64
  waitUntil: {
49
- less_than: getCurrentDate().toISOString()
65
+ less_than: nowISOString
50
66
  }
51
67
  }
52
68
  ]
53
69
  }
54
70
  ];
55
- if (allQueues !== true) {
71
+ if (!id && allQueues !== true) {
56
72
  and.push({
57
73
  queue: {
58
74
  equals: queue ?? 'default'
@@ -62,10 +78,16 @@ export const runJobs = async (args)=>{
62
78
  if (whereFromProps) {
63
79
  and.push(whereFromProps);
64
80
  }
65
- // Only enforce concurrency controls if the feature is enabled
66
- if (jobsConfig.enableConcurrencyControl) {
67
- // Find currently running jobs with concurrency keys to enforce exclusive concurrency
68
- // Jobs with the same concurrencyKey should not run in parallel
81
+ if (id) {
82
+ and.push({
83
+ id: {
84
+ equals: id
85
+ }
86
+ });
87
+ }
88
+ if (jobsConfig.hasConcurrency) {
89
+ // Find currently running jobs with concurrency keys to enforce exclusive concurrency.
90
+ // Jobs with the same concurrencyKey should not run in parallel.
69
91
  const runningJobsWithConcurrency = await payload.db.find({
70
92
  collection: jobsCollectionSlug,
71
93
  limit: 0,
@@ -79,8 +101,8 @@ export const runJobs = async (args)=>{
79
101
  where: {
80
102
  and: [
81
103
  {
82
- processing: {
83
- equals: true
104
+ processingUntil: {
105
+ greater_than: nowISOString
84
106
  }
85
107
  },
86
108
  {
@@ -122,23 +144,24 @@ export const runJobs = async (args)=>{
122
144
  });
123
145
  }
124
146
  }
125
- // Find all jobs and ensure we set job to processing: true as early as possible to reduce the chance of
126
- // the same job being picked up by another worker
147
+ // Claim jobs before running them so another worker cannot pick up the same jobs.
148
+ // `processingToken` identifies which jobs were claimed by this runner.
127
149
  let jobs = [];
128
150
  if (id) {
129
- // Only one job to run
130
- const job = await updateJob({
131
- id,
151
+ const updatedDocs = await updateJobs({
132
152
  data: {
133
- processing: true
153
+ processingToken,
154
+ processingUntil
134
155
  },
156
+ limit: 1,
135
157
  req,
136
- returning: true
158
+ returning: true,
159
+ where: {
160
+ and
161
+ }
137
162
  });
138
- if (job) {
139
- jobs = [
140
- job
141
- ];
163
+ if (updatedDocs) {
164
+ jobs = updatedDocs;
142
165
  }
143
166
  } else {
144
167
  let defaultProcessingOrder = payload.collections[jobsCollectionSlug]?.config.defaultSort ?? 'createdAt';
@@ -156,7 +179,8 @@ export const runJobs = async (args)=>{
156
179
  }
157
180
  const updatedDocs = await updateJobs({
158
181
  data: {
159
- processing: true
182
+ processingToken,
183
+ processingUntil
160
184
  },
161
185
  limit,
162
186
  req,
@@ -176,10 +200,9 @@ export const runJobs = async (args)=>{
176
200
  remainingJobsFromQueried: 0
177
201
  };
178
202
  }
179
- // Only handle concurrency deduplication if the feature is enabled
180
- if (jobsConfig.enableConcurrencyControl) {
181
- // Handle the case where multiple jobs with the same concurrencyKey were picked up in the same batch
182
- // We should only run one job per concurrencyKey, release the others back to pending
203
+ if (jobsConfig.hasConcurrency) {
204
+ // Handle the case where multiple jobs with the same concurrencyKey were picked up in the same batch.
205
+ // We should only run one job per concurrencyKey, releasing the others back to pending.
183
206
  const seenConcurrencyKeys = new Set();
184
207
  const jobsToRun = [];
185
208
  const jobsToRelease = [];
@@ -201,25 +224,39 @@ export const runJobs = async (args)=>{
201
224
  const releaseIds = jobsToRelease.map((job)=>job.id);
202
225
  await updateJobs({
203
226
  data: {
204
- processing: false
227
+ processingUntil: null
205
228
  },
206
229
  req,
207
230
  returning: false,
208
231
  where: {
209
- id: {
210
- in: releaseIds
211
- }
232
+ and: [
233
+ {
234
+ id: {
235
+ in: releaseIds
236
+ }
237
+ },
238
+ {
239
+ processingToken: {
240
+ equals: processingToken
241
+ }
242
+ },
243
+ {
244
+ processingUntil: {
245
+ greater_than: new Date(getCurrentDate().getTime() + processingLeaseSafetyBuffer).toISOString()
246
+ }
247
+ }
248
+ ]
212
249
  }
213
250
  });
214
251
  }
215
252
  // Use only the filtered jobs going forward
216
253
  jobs = jobsToRun;
217
- }
218
- if (!jobs.length) {
219
- return {
220
- noJobsRemaining: false,
221
- remainingJobsFromQueried: 0
222
- };
254
+ if (!jobs.length) {
255
+ return {
256
+ noJobsRemaining: false,
257
+ remainingJobsFromQueried: 0
258
+ };
259
+ }
223
260
  }
224
261
  if (!silent || typeof silent === 'object' && !silent.info) {
225
262
  let newCount = 0;
@@ -259,31 +296,31 @@ export const runJobs = async (args)=>{
259
296
  };
260
297
  }
261
298
  }
262
- if (!workflowConfig) {
263
- // Permanently fail jobs whose task/workflow slug is no longer registered in config — they can never complete.
264
- const errorMessage = `${job.taskSlug ? `Task '${job.taskSlug}'` : `Workflow '${job.workflowSlug}'`} is not registered in payload.config.jobs.`;
265
- if (!silent || typeof silent === 'object' && !silent.error) {
266
- payload.logger.error({
267
- msg: `Error running job ${job.workflowSlug || `Task: ${job.taskSlug}`} id: ${job.id} - ${errorMessage}`
299
+ try {
300
+ if (!workflowConfig) {
301
+ // Permanently fail jobs whose task/workflow slug is no longer registered in config — they can never complete.
302
+ const errorMessage = `${job.taskSlug ? `Task '${job.taskSlug}'` : `Workflow '${job.workflowSlug}'`} is not registered in payload.config.jobs.`;
303
+ if (!silent || typeof silent === 'object' && !silent.error) {
304
+ payload.logger.error({
305
+ msg: `Error running job ${job.workflowSlug || `Task: ${job.taskSlug}`} id: ${job.id} - ${errorMessage}`
306
+ });
307
+ }
308
+ const updateJob = getUpdateJobFunction(job, jobReq);
309
+ await updateJob({
310
+ error: {
311
+ message: errorMessage
312
+ },
313
+ hasError: true,
314
+ processingUntil: null,
315
+ totalTried: (job.totalTried ?? 0) + 1
268
316
  });
317
+ return {
318
+ id: job.id,
319
+ result: {
320
+ status: 'error-reached-max-retries'
321
+ }
322
+ };
269
323
  }
270
- const updateJob = getUpdateJobFunction(job, jobReq);
271
- await updateJob({
272
- error: {
273
- message: errorMessage
274
- },
275
- hasError: true,
276
- processing: false,
277
- totalTried: (job.totalTried ?? 0) + 1
278
- });
279
- return {
280
- id: job.id,
281
- result: {
282
- status: 'error-reached-max-retries'
283
- }
284
- };
285
- }
286
- try {
287
324
  const updateJob = getUpdateJobFunction(job, jobReq);
288
325
  // the runner will either be passed to the config
289
326
  // OR it will be a path, which we will need to import via eval to avoid
@@ -304,7 +341,7 @@ export const runJobs = async (args)=>{
304
341
  error: errorMessage
305
342
  },
306
343
  hasError: true,
307
- processing: false
344
+ processingUntil: null
308
345
  });
309
346
  return {
310
347
  id: job.id,
@@ -348,24 +385,24 @@ export const runJobs = async (args)=>{
348
385
  };
349
386
  }
350
387
  } catch (error) {
388
+ if (error instanceof JobRunAbortedError) {
389
+ return null;
390
+ }
351
391
  if (error instanceof JobCancelledError) {
352
- if (!job.error?.cancelled || !job.hasError || job.processing || job.completedAt || job.waitUntil) {
392
+ if (!job.error?.cancelled || !job.hasError || job.processingUntil || job.completedAt || job.waitUntil) {
353
393
  // When using the local API to cancel jobs, the local API will update the job data for us to ensure the job is cancelled.
354
394
  // But when throwing a JobCancelledError within a task or workflow handler, we are responsible for updating the job data ourselves.
395
+ // Use the lease-protected getUpdateJobFunction so an old worker cannot cancel the job after another worker claims it.
396
+ const updateJob = getUpdateJobFunction(job, jobReq);
355
397
  await updateJob({
356
- id: job.id,
357
- data: {
358
- completedAt: null,
359
- error: {
360
- cancelled: true,
361
- message: error.message
362
- },
363
- hasError: true,
364
- processing: false,
365
- waitUntil: null
398
+ completedAt: null,
399
+ error: {
400
+ cancelled: true,
401
+ message: error.message
366
402
  },
367
- req,
368
- returning: false
403
+ hasError: true,
404
+ processingUntil: null,
405
+ waitUntil: null
369
406
  });
370
407
  }
371
408
  return {
@@ -378,17 +415,29 @@ export const runJobs = async (args)=>{
378
415
  throw error;
379
416
  }
380
417
  };
418
+ const stopHeartbeat = startProcessingLeaseHeartbeat({
419
+ jobIDs: jobs.map((job)=>job.id),
420
+ processingLeaseDuration,
421
+ processingLeaseSafetyBuffer,
422
+ processingToken,
423
+ req,
424
+ silent
425
+ });
381
426
  let resultsArray = [];
382
- if (sequential) {
383
- for (const job of jobs){
384
- const result = await runSingleJob(job);
385
- if (result) {
386
- resultsArray.push(result);
427
+ try {
428
+ if (sequential) {
429
+ for (const job of jobs){
430
+ const result = await runSingleJob(job);
431
+ if (result) {
432
+ resultsArray.push(result);
433
+ }
387
434
  }
435
+ } else {
436
+ const jobPromises = jobs.map(runSingleJob);
437
+ resultsArray = (await Promise.all(jobPromises)).filter((result)=>result !== null);
388
438
  }
389
- } else {
390
- const jobPromises = jobs.map(runSingleJob);
391
- resultsArray = await Promise.all(jobPromises);
439
+ } finally{
440
+ stopHeartbeat();
392
441
  }
393
442
  if (jobsConfig.deleteJobOnComplete && successfullyCompletedJobs.length) {
394
443
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/queues/operations/runJobs/index.ts"],"sourcesContent":["import type { Job } from '../../../index.js'\nimport type { PayloadRequest, Sort, Where } from '../../../types/index.js'\nimport type { WorkflowJSON } from '../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig, WorkflowHandler } from '../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../localAPI.js'\nimport type { RunJobResult } from './runJob/index.js'\n\nimport { Forbidden } from '../../../errors/Forbidden.js'\nimport { isolateObjectProperty } from '../../../utilities/isolateObjectProperty.js'\nimport { jobsCollectionSlug } from '../../config/collection.js'\nimport { JobCancelledError } from '../../errors/index.js'\nimport { getCurrentDate } from '../../utilities/getCurrentDate.js'\nimport { updateJob, updateJobs } from '../../utilities/updateJob.js'\nimport { getUpdateJobFunction } from './runJob/getUpdateJobFunction.js'\nimport { importHandlerPath } from './runJob/importHandlerPath.js'\nimport { runJob } from './runJob/index.js'\nimport { runJSONJob } from './runJSONJob/index.js'\n\nexport type RunJobsArgs = {\n /**\n * If you want to run jobs from all queues, set this to true.\n * If you set this to true, the `queue` property will be ignored.\n *\n * @default false\n */\n allQueues?: boolean\n /**\n * ID of the job to run\n */\n id?: number | string\n /**\n * The maximum number of jobs to run in this invocation\n *\n * @default 10\n */\n limit?: number\n overrideAccess?: boolean\n /**\n * Adjust the job processing order\n *\n * FIFO would equal `createdAt` and LIFO would equal `-createdAt`.\n *\n * @default all jobs for all queues will be executed in FIFO order.\n */\n processingOrder?: Sort\n /**\n * If you want to run jobs from a specific queue, set this to the queue name.\n *\n * @default jobs from the `default` queue will be executed.\n */\n queue?: string\n req: PayloadRequest\n /**\n * By default, jobs are run in parallel.\n * If you want to run them in sequence, set this to true.\n */\n sequential?: boolean\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n where?: Where\n}\n\nexport type RunJobsResult = {\n jobStatus?: Record<string, RunJobResult>\n /**\n * If this is true, there for sure are no jobs remaining, regardless of the limit\n */\n noJobsRemaining?: boolean\n /**\n * Out of the jobs that were queried & processed (within the set limit), how many are remaining and retryable?\n */\n remainingJobsFromQueried: number\n}\n\nexport const runJobs = async (args: RunJobsArgs): Promise<RunJobsResult> => {\n const {\n id,\n allQueues = false,\n limit = 10,\n overrideAccess,\n processingOrder,\n queue = 'default',\n req,\n req: {\n payload,\n payload: {\n config: { jobs: jobsConfig },\n },\n },\n sequential,\n silent = false,\n where: whereFromProps,\n } = args\n\n if (!overrideAccess) {\n /**\n * By default, jobsConfig.access.run will be `defaultAccess` which is a function that returns `true` if the user is logged in.\n */\n const accessFn = jobsConfig?.access?.run ?? (() => true)\n const hasAccess = await accessFn({ req })\n if (!hasAccess) {\n throw new Forbidden(req.t)\n }\n }\n const and: Where[] = [\n {\n completedAt: {\n exists: false,\n },\n },\n {\n hasError: {\n not_equals: true,\n },\n },\n {\n processing: {\n equals: false,\n },\n },\n {\n or: [\n {\n waitUntil: {\n exists: false,\n },\n },\n {\n waitUntil: {\n less_than: getCurrentDate().toISOString(),\n },\n },\n ],\n },\n ]\n\n if (allQueues !== true) {\n and.push({\n queue: {\n equals: queue ?? 'default',\n },\n })\n }\n\n if (whereFromProps) {\n and.push(whereFromProps)\n }\n\n // Only enforce concurrency controls if the feature is enabled\n if (jobsConfig.enableConcurrencyControl) {\n // Find currently running jobs with concurrency keys to enforce exclusive concurrency\n // Jobs with the same concurrencyKey should not run in parallel\n const runningJobsWithConcurrency = await payload.db.find({\n collection: jobsCollectionSlug,\n limit: 0,\n pagination: false,\n req: { transactionID: undefined },\n select: {\n concurrencyKey: true,\n },\n where: {\n and: [{ processing: { equals: true } }, { concurrencyKey: { exists: true } }],\n },\n })\n\n const runningConcurrencyKeys = new Set<string>()\n if (runningJobsWithConcurrency?.docs) {\n for (const doc of runningJobsWithConcurrency.docs) {\n const concurrencyKey = (doc as Job).concurrencyKey\n if (concurrencyKey) {\n runningConcurrencyKeys.add(concurrencyKey)\n }\n }\n }\n\n // Exclude jobs whose concurrencyKey is already running\n if (runningConcurrencyKeys.size > 0) {\n and.push({\n or: [\n // Jobs without a concurrency key can always run\n { concurrencyKey: { exists: false } },\n // Jobs with a concurrency key that is not currently running can run\n { concurrencyKey: { not_in: [...runningConcurrencyKeys] } },\n ],\n })\n }\n }\n\n // Find all jobs and ensure we set job to processing: true as early as possible to reduce the chance of\n // the same job being picked up by another worker\n let jobs: Job[] = []\n\n if (id) {\n // Only one job to run\n const job = await updateJob({\n id,\n data: {\n processing: true,\n },\n req,\n returning: true,\n })\n if (job) {\n jobs = [job]\n }\n } else {\n let defaultProcessingOrder: Sort =\n payload.collections[jobsCollectionSlug]?.config.defaultSort ?? 'createdAt'\n\n const processingOrderConfig = jobsConfig.processingOrder\n if (typeof processingOrderConfig === 'function') {\n defaultProcessingOrder = await processingOrderConfig(args)\n } else if (typeof processingOrderConfig === 'object' && !Array.isArray(processingOrderConfig)) {\n if (\n !allQueues &&\n queue &&\n processingOrderConfig.queues &&\n processingOrderConfig.queues[queue]\n ) {\n defaultProcessingOrder = processingOrderConfig.queues[queue]\n } else if (processingOrderConfig.default) {\n defaultProcessingOrder = processingOrderConfig.default\n }\n } else if (typeof processingOrderConfig === 'string') {\n defaultProcessingOrder = processingOrderConfig\n }\n const updatedDocs = await updateJobs({\n data: {\n processing: true,\n },\n limit,\n req,\n returning: true,\n sort: processingOrder ?? defaultProcessingOrder,\n where: { and },\n })\n\n if (updatedDocs) {\n jobs = updatedDocs\n }\n }\n\n if (!jobs.length) {\n return {\n noJobsRemaining: true,\n remainingJobsFromQueried: 0,\n }\n }\n\n // Only handle concurrency deduplication if the feature is enabled\n if (jobsConfig.enableConcurrencyControl) {\n // Handle the case where multiple jobs with the same concurrencyKey were picked up in the same batch\n // We should only run one job per concurrencyKey, release the others back to pending\n const seenConcurrencyKeys = new Set<string>()\n const jobsToRun: Job[] = []\n const jobsToRelease: Job[] = []\n\n for (const job of jobs) {\n if (job.concurrencyKey) {\n if (seenConcurrencyKeys.has(job.concurrencyKey)) {\n // This job has the same concurrencyKey as another job we're already running\n jobsToRelease.push(job)\n } else {\n seenConcurrencyKeys.add(job.concurrencyKey)\n jobsToRun.push(job)\n }\n } else {\n jobsToRun.push(job)\n }\n }\n\n // Release duplicate concurrencyKey jobs back to pending state\n if (jobsToRelease.length > 0) {\n const releaseIds = jobsToRelease.map((job) => job.id)\n await updateJobs({\n data: { processing: false },\n req,\n returning: false,\n where: { id: { in: releaseIds } },\n })\n }\n\n // Use only the filtered jobs going forward\n jobs = jobsToRun\n }\n\n if (!jobs.length) {\n return {\n noJobsRemaining: false,\n remainingJobsFromQueried: 0,\n }\n }\n\n if (!silent || (typeof silent === 'object' && !silent.info)) {\n let newCount = 0\n let retryCount = 0\n\n for (const job of jobs) {\n if (job.totalTried > 0) {\n retryCount++\n } else {\n newCount++\n }\n }\n\n payload.logger.info({\n msg: `Running ${jobs.length} jobs.`,\n new: newCount,\n retrying: retryCount,\n })\n }\n\n const successfullyCompletedJobs: (number | string)[] = []\n\n const runSingleJob = async (\n job: Job,\n ): Promise<{\n id: number | string\n result: RunJobResult\n }> => {\n if (!job.workflowSlug && !job.taskSlug) {\n throw new Error('Job must have either a workflowSlug or a taskSlug')\n }\n const jobReq = isolateObjectProperty(req, 'transactionID')\n\n let workflowConfig: undefined | WorkflowConfig = undefined\n\n if (job.workflowSlug && jobsConfig.workflows?.length) {\n workflowConfig = jobsConfig.workflows.find(({ slug }) => slug === job.workflowSlug)\n } else if (job.taskSlug && jobsConfig.tasks?.length) {\n const taskExists = jobsConfig.tasks.some(({ slug }) => slug === job.taskSlug)\n if (taskExists) {\n workflowConfig = {\n slug: 'singleTask',\n handler: async ({ job, tasks }) => {\n await tasks[job.taskSlug as string]!('1', {\n input: job.input,\n })\n },\n }\n }\n }\n\n if (!workflowConfig) {\n // Permanently fail jobs whose task/workflow slug is no longer registered in config — they can never complete.\n const errorMessage = `${job.taskSlug ? `Task '${job.taskSlug}'` : `Workflow '${job.workflowSlug}'`} is not registered in payload.config.jobs.`\n\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n msg: `Error running job ${job.workflowSlug || `Task: ${job.taskSlug}`} id: ${job.id} - ${errorMessage}`,\n })\n }\n\n const updateJob = getUpdateJobFunction(job, jobReq)\n await updateJob({\n error: { message: errorMessage },\n hasError: true,\n processing: false,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n\n try {\n const updateJob = getUpdateJobFunction(job, jobReq)\n\n // the runner will either be passed to the config\n // OR it will be a path, which we will need to import via eval to avoid\n // Next.js compiler dynamic import expression errors\n let workflowHandler: WorkflowHandler | WorkflowJSON\n if (\n typeof workflowConfig.handler === 'function' ||\n (typeof workflowConfig.handler === 'object' && Array.isArray(workflowConfig.handler))\n ) {\n workflowHandler = workflowConfig.handler\n } else {\n workflowHandler = await importHandlerPath<typeof workflowHandler>(workflowConfig.handler)\n\n if (!workflowHandler) {\n const jobLabel = job.workflowSlug || `Task: ${job.taskSlug}`\n const errorMessage = `Can't find runner while importing with the path ${workflowConfig.handler} in job type ${jobLabel}.`\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error(errorMessage)\n }\n\n await updateJob({\n error: {\n error: errorMessage,\n },\n hasError: true,\n processing: false,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n }\n\n if (typeof workflowHandler === 'function') {\n const result = await runJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n } else {\n const result = await runJSONJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n }\n } catch (error) {\n if (error instanceof JobCancelledError) {\n if (\n !(job.error as Record<string, unknown> | undefined)?.cancelled ||\n !job.hasError ||\n job.processing ||\n job.completedAt ||\n job.waitUntil\n ) {\n // When using the local API to cancel jobs, the local API will update the job data for us to ensure the job is cancelled.\n // But when throwing a JobCancelledError within a task or workflow handler, we are responsible for updating the job data ourselves.\n await updateJob({\n id: job.id,\n data: {\n completedAt: null,\n error: {\n cancelled: true,\n message: error.message,\n },\n hasError: true,\n processing: false,\n waitUntil: null,\n },\n req,\n returning: false,\n })\n }\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n throw error\n }\n }\n\n let resultsArray: { id: number | string; result: RunJobResult }[] = []\n if (sequential) {\n for (const job of jobs) {\n const result = await runSingleJob(job)\n if (result) {\n resultsArray.push(result)\n }\n }\n } else {\n const jobPromises = jobs.map(runSingleJob)\n resultsArray = (await Promise.all(jobPromises)) as {\n id: number | string\n result: RunJobResult\n }[]\n }\n\n if (jobsConfig.deleteJobOnComplete && successfullyCompletedJobs.length) {\n try {\n await payload.db.deleteMany({\n collection: jobsCollectionSlug,\n where: { id: { in: successfullyCompletedJobs } },\n })\n } catch (err) {\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n err,\n msg: `Failed to delete jobs ${successfullyCompletedJobs.join(', ')} on complete`,\n })\n }\n }\n }\n\n const resultsObject: RunJobsResult['jobStatus'] = resultsArray.reduce(\n (acc, cur) => {\n if (cur !== null) {\n // Check if there's a valid result to include\n acc[cur.id] = cur.result\n }\n return acc\n },\n {} as Record<string, RunJobResult>,\n )\n\n let remainingJobsFromQueried = 0\n for (const jobID in resultsObject) {\n const jobResult = resultsObject[jobID]\n if (jobResult?.status === 'error') {\n remainingJobsFromQueried++ // Can be retried\n }\n }\n\n return {\n jobStatus: resultsObject,\n remainingJobsFromQueried,\n }\n}\n"],"names":["Forbidden","isolateObjectProperty","jobsCollectionSlug","JobCancelledError","getCurrentDate","updateJob","updateJobs","getUpdateJobFunction","importHandlerPath","runJob","runJSONJob","runJobs","args","id","allQueues","limit","overrideAccess","processingOrder","queue","req","payload","config","jobs","jobsConfig","sequential","silent","where","whereFromProps","accessFn","access","run","hasAccess","t","and","completedAt","exists","hasError","not_equals","processing","equals","or","waitUntil","less_than","toISOString","push","enableConcurrencyControl","runningJobsWithConcurrency","db","find","collection","pagination","transactionID","undefined","select","concurrencyKey","runningConcurrencyKeys","Set","docs","doc","add","size","not_in","job","data","returning","defaultProcessingOrder","collections","defaultSort","processingOrderConfig","Array","isArray","queues","default","updatedDocs","sort","length","noJobsRemaining","remainingJobsFromQueried","seenConcurrencyKeys","jobsToRun","jobsToRelease","has","releaseIds","map","in","info","newCount","retryCount","totalTried","logger","msg","new","retrying","successfullyCompletedJobs","runSingleJob","workflowSlug","taskSlug","Error","jobReq","workflowConfig","workflows","slug","tasks","taskExists","some","handler","input","errorMessage","error","message","result","status","workflowHandler","jobLabel","cancelled","resultsArray","jobPromises","Promise","all","deleteJobOnComplete","deleteMany","err","join","resultsObject","reduce","acc","cur","jobID","jobResult","jobStatus"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/queues/operations/runJobs/index.ts"],"sourcesContent":["import { v4 as uuid } from 'uuid'\n\nimport type { Job } from '../../../index.js'\nimport type { PayloadRequest, Sort, Where } from '../../../types/index.js'\nimport type { WorkflowJSON } from '../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig, WorkflowHandler } from '../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../localAPI.js'\nimport type { RunJobResult } from './runJob/index.js'\n\nimport { Forbidden } from '../../../errors/Forbidden.js'\nimport { isolateObjectProperty } from '../../../utilities/isolateObjectProperty.js'\nimport { jobsCollectionSlug } from '../../config/collection.js'\nimport { JobCancelledError, JobRunAbortedError } from '../../errors/index.js'\nimport { getCurrentDate } from '../../utilities/getCurrentDate.js'\nimport { updateJobs } from '../../utilities/updateJob.js'\nimport { startProcessingLeaseHeartbeat } from './heartbeat.js'\nimport { getUpdateJobFunction } from './runJob/getUpdateJobFunction.js'\nimport { importHandlerPath } from './runJob/importHandlerPath.js'\nimport { runJob } from './runJob/index.js'\nimport { runJSONJob } from './runJSONJob/index.js'\n\nexport type RunJobsArgs = {\n /**\n * If you want to run jobs from all queues, set this to true.\n * If you set this to true, the `queue` property will be ignored.\n *\n * @default false\n */\n allQueues?: boolean\n /**\n * ID of the job to run\n */\n id?: number | string\n /**\n * The maximum number of jobs to run in this invocation\n *\n * @default 10\n */\n limit?: number\n overrideAccess?: boolean\n /**\n * Adjust the job processing order\n *\n * FIFO would equal `createdAt` and LIFO would equal `-createdAt`.\n *\n * @default all jobs for all queues will be executed in FIFO order.\n */\n processingOrder?: Sort\n /**\n * If you want to run jobs from a specific queue, set this to the queue name.\n *\n * @default jobs from the `default` queue will be executed.\n */\n queue?: string\n req: PayloadRequest\n /**\n * By default, jobs are run in parallel.\n * If you want to run them in sequence, set this to true.\n */\n sequential?: boolean\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n where?: Where\n}\n\nexport type RunJobsResult = {\n jobStatus?: Record<string, RunJobResult>\n /**\n * If this is true, there for sure are no jobs remaining, regardless of the limit\n */\n noJobsRemaining?: boolean\n /**\n * Out of the jobs that were queried & processed (within the set limit), how many are remaining and retryable?\n */\n remainingJobsFromQueried: number\n}\n\nexport const runJobs = async (args: RunJobsArgs): Promise<RunJobsResult> => {\n const {\n id,\n allQueues = false,\n limit = 10,\n overrideAccess,\n processingOrder,\n queue = 'default',\n req,\n req: {\n payload,\n payload: {\n config: { jobs: jobsConfig },\n },\n },\n sequential,\n silent = false,\n where: whereFromProps,\n } = args\n\n if (!overrideAccess) {\n /**\n * By default, jobsConfig.access.run will be `defaultAccess` which is a function that returns `true` if the user is logged in.\n */\n const accessFn = jobsConfig?.access?.run ?? (() => true)\n const hasAccess = await accessFn({ req })\n if (!hasAccess) {\n throw new Forbidden(req.t)\n }\n }\n const now = getCurrentDate()\n const { duration: processingLeaseDuration, safetyBuffer: processingLeaseSafetyBuffer } =\n jobsConfig.processingLease\n const nowISOString = now.toISOString()\n const processingUntil = new Date(now.getTime() + processingLeaseDuration).toISOString()\n const processingToken = uuid()\n const and: Where[] = [\n {\n completedAt: {\n exists: false,\n },\n },\n {\n hasError: {\n not_equals: true,\n },\n },\n {\n or: [\n { processingUntil: { exists: false } },\n { processingUntil: { less_than_equal: nowISOString } },\n ],\n },\n {\n or: [\n {\n waitUntil: {\n exists: false,\n },\n },\n {\n waitUntil: {\n less_than: nowISOString,\n },\n },\n ],\n },\n ]\n\n if (!id && allQueues !== true) {\n and.push({\n queue: {\n equals: queue ?? 'default',\n },\n })\n }\n\n if (whereFromProps) {\n and.push(whereFromProps)\n }\n\n if (id) {\n and.push({ id: { equals: id } })\n }\n\n if (jobsConfig.hasConcurrency) {\n // Find currently running jobs with concurrency keys to enforce exclusive concurrency.\n // Jobs with the same concurrencyKey should not run in parallel.\n const runningJobsWithConcurrency = await payload.db.find({\n collection: jobsCollectionSlug,\n limit: 0,\n pagination: false,\n req: { transactionID: undefined },\n select: {\n concurrencyKey: true,\n },\n where: {\n and: [\n { processingUntil: { greater_than: nowISOString } },\n { concurrencyKey: { exists: true } },\n ],\n },\n })\n\n const runningConcurrencyKeys = new Set<string>()\n if (runningJobsWithConcurrency?.docs) {\n for (const doc of runningJobsWithConcurrency.docs) {\n const concurrencyKey = (doc as Job).concurrencyKey\n if (concurrencyKey) {\n runningConcurrencyKeys.add(concurrencyKey)\n }\n }\n }\n\n // Exclude jobs whose concurrencyKey is already running\n if (runningConcurrencyKeys.size > 0) {\n and.push({\n or: [\n // Jobs without a concurrency key can always run\n { concurrencyKey: { exists: false } },\n // Jobs with a concurrency key that is not currently running can run\n { concurrencyKey: { not_in: [...runningConcurrencyKeys] } },\n ],\n })\n }\n }\n\n // Claim jobs before running them so another worker cannot pick up the same jobs.\n // `processingToken` identifies which jobs were claimed by this runner.\n let jobs: Job[] = []\n\n if (id) {\n const updatedDocs = await updateJobs({\n data: {\n processingToken,\n processingUntil,\n },\n limit: 1,\n req,\n returning: true,\n where: { and },\n })\n if (updatedDocs) {\n jobs = updatedDocs\n }\n } else {\n let defaultProcessingOrder: Sort =\n payload.collections[jobsCollectionSlug]?.config.defaultSort ?? 'createdAt'\n\n const processingOrderConfig = jobsConfig.processingOrder\n if (typeof processingOrderConfig === 'function') {\n defaultProcessingOrder = await processingOrderConfig(args)\n } else if (typeof processingOrderConfig === 'object' && !Array.isArray(processingOrderConfig)) {\n if (\n !allQueues &&\n queue &&\n processingOrderConfig.queues &&\n processingOrderConfig.queues[queue]\n ) {\n defaultProcessingOrder = processingOrderConfig.queues[queue]\n } else if (processingOrderConfig.default) {\n defaultProcessingOrder = processingOrderConfig.default\n }\n } else if (typeof processingOrderConfig === 'string') {\n defaultProcessingOrder = processingOrderConfig\n }\n const updatedDocs = await updateJobs({\n data: {\n processingToken,\n processingUntil,\n },\n limit,\n req,\n returning: true,\n sort: processingOrder ?? defaultProcessingOrder,\n where: { and },\n })\n\n if (updatedDocs) {\n jobs = updatedDocs\n }\n }\n\n if (!jobs.length) {\n return {\n noJobsRemaining: true,\n remainingJobsFromQueried: 0,\n }\n }\n\n if (jobsConfig.hasConcurrency) {\n // Handle the case where multiple jobs with the same concurrencyKey were picked up in the same batch.\n // We should only run one job per concurrencyKey, releasing the others back to pending.\n const seenConcurrencyKeys = new Set<string>()\n const jobsToRun: Job[] = []\n const jobsToRelease: Job[] = []\n\n for (const job of jobs) {\n if (job.concurrencyKey) {\n if (seenConcurrencyKeys.has(job.concurrencyKey)) {\n // This job has the same concurrencyKey as another job we're already running\n jobsToRelease.push(job)\n } else {\n seenConcurrencyKeys.add(job.concurrencyKey)\n jobsToRun.push(job)\n }\n } else {\n jobsToRun.push(job)\n }\n }\n\n // Release duplicate concurrencyKey jobs back to pending state\n if (jobsToRelease.length > 0) {\n const releaseIds = jobsToRelease.map((job) => job.id)\n await updateJobs({\n data: { processingUntil: null },\n req,\n returning: false,\n where: {\n and: [\n { id: { in: releaseIds } },\n { processingToken: { equals: processingToken } },\n {\n processingUntil: {\n greater_than: new Date(\n getCurrentDate().getTime() + processingLeaseSafetyBuffer,\n ).toISOString(),\n },\n },\n ],\n },\n })\n }\n\n // Use only the filtered jobs going forward\n jobs = jobsToRun\n\n if (!jobs.length) {\n return {\n noJobsRemaining: false,\n remainingJobsFromQueried: 0,\n }\n }\n }\n\n if (!silent || (typeof silent === 'object' && !silent.info)) {\n let newCount = 0\n let retryCount = 0\n\n for (const job of jobs) {\n if (job.totalTried > 0) {\n retryCount++\n } else {\n newCount++\n }\n }\n\n payload.logger.info({\n msg: `Running ${jobs.length} jobs.`,\n new: newCount,\n retrying: retryCount,\n })\n }\n\n const successfullyCompletedJobs: (number | string)[] = []\n\n const runSingleJob = async (\n job: Job,\n ): Promise<{\n id: number | string\n result: RunJobResult\n } | null> => {\n if (!job.workflowSlug && !job.taskSlug) {\n throw new Error('Job must have either a workflowSlug or a taskSlug')\n }\n const jobReq = isolateObjectProperty(req, 'transactionID')\n\n let workflowConfig: undefined | WorkflowConfig = undefined\n\n if (job.workflowSlug && jobsConfig.workflows?.length) {\n workflowConfig = jobsConfig.workflows.find(({ slug }) => slug === job.workflowSlug)\n } else if (job.taskSlug && jobsConfig.tasks?.length) {\n const taskExists = jobsConfig.tasks.some(({ slug }) => slug === job.taskSlug)\n if (taskExists) {\n workflowConfig = {\n slug: 'singleTask',\n handler: async ({ job, tasks }) => {\n await tasks[job.taskSlug as string]!('1', {\n input: job.input,\n })\n },\n }\n }\n }\n\n try {\n if (!workflowConfig) {\n // Permanently fail jobs whose task/workflow slug is no longer registered in config — they can never complete.\n const errorMessage = `${job.taskSlug ? `Task '${job.taskSlug}'` : `Workflow '${job.workflowSlug}'`} is not registered in payload.config.jobs.`\n\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n msg: `Error running job ${job.workflowSlug || `Task: ${job.taskSlug}`} id: ${job.id} - ${errorMessage}`,\n })\n }\n\n const updateJob = getUpdateJobFunction(job, jobReq)\n await updateJob({\n error: { message: errorMessage },\n hasError: true,\n processingUntil: null,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n\n const updateJob = getUpdateJobFunction(job, jobReq)\n\n // the runner will either be passed to the config\n // OR it will be a path, which we will need to import via eval to avoid\n // Next.js compiler dynamic import expression errors\n let workflowHandler: WorkflowHandler | WorkflowJSON\n if (\n typeof workflowConfig.handler === 'function' ||\n (typeof workflowConfig.handler === 'object' && Array.isArray(workflowConfig.handler))\n ) {\n workflowHandler = workflowConfig.handler\n } else {\n workflowHandler = await importHandlerPath<typeof workflowHandler>(workflowConfig.handler)\n\n if (!workflowHandler) {\n const jobLabel = job.workflowSlug || `Task: ${job.taskSlug}`\n const errorMessage = `Can't find runner while importing with the path ${workflowConfig.handler} in job type ${jobLabel}.`\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error(errorMessage)\n }\n\n await updateJob({\n error: {\n error: errorMessage,\n },\n hasError: true,\n processingUntil: null,\n })\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n }\n\n if (typeof workflowHandler === 'function') {\n const result = await runJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n } else {\n const result = await runJSONJob({\n job,\n req: jobReq,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n\n if (result.status === 'success') {\n successfullyCompletedJobs.push(job.id)\n }\n\n return { id: job.id, result }\n }\n } catch (error) {\n if (error instanceof JobRunAbortedError) {\n return null\n }\n if (error instanceof JobCancelledError) {\n if (\n !(job.error as Record<string, unknown> | undefined)?.cancelled ||\n !job.hasError ||\n job.processingUntil ||\n job.completedAt ||\n job.waitUntil\n ) {\n // When using the local API to cancel jobs, the local API will update the job data for us to ensure the job is cancelled.\n // But when throwing a JobCancelledError within a task or workflow handler, we are responsible for updating the job data ourselves.\n // Use the lease-protected getUpdateJobFunction so an old worker cannot cancel the job after another worker claims it.\n const updateJob = getUpdateJobFunction(job, jobReq)\n await updateJob({\n completedAt: null,\n error: {\n cancelled: true,\n message: error.message,\n },\n hasError: true,\n processingUntil: null,\n waitUntil: null,\n })\n }\n\n return {\n id: job.id,\n result: {\n status: 'error-reached-max-retries',\n },\n }\n }\n throw error\n }\n }\n\n const stopHeartbeat = startProcessingLeaseHeartbeat({\n jobIDs: jobs.map((job) => job.id),\n processingLeaseDuration,\n processingLeaseSafetyBuffer,\n processingToken,\n req,\n silent,\n })\n\n let resultsArray: { id: number | string; result: RunJobResult }[] = []\n try {\n if (sequential) {\n for (const job of jobs) {\n const result = await runSingleJob(job)\n if (result) {\n resultsArray.push(result)\n }\n }\n } else {\n const jobPromises = jobs.map(runSingleJob)\n resultsArray = (await Promise.all(jobPromises)).filter((result) => result !== null)\n }\n } finally {\n stopHeartbeat()\n }\n\n if (jobsConfig.deleteJobOnComplete && successfullyCompletedJobs.length) {\n try {\n await payload.db.deleteMany({\n collection: jobsCollectionSlug,\n where: { id: { in: successfullyCompletedJobs } },\n })\n } catch (err) {\n if (!silent || (typeof silent === 'object' && !silent.error)) {\n payload.logger.error({\n err,\n msg: `Failed to delete jobs ${successfullyCompletedJobs.join(', ')} on complete`,\n })\n }\n }\n }\n\n const resultsObject: RunJobsResult['jobStatus'] = resultsArray.reduce(\n (acc, cur) => {\n if (cur !== null) {\n // Check if there's a valid result to include\n acc[cur.id] = cur.result\n }\n return acc\n },\n {} as Record<string, RunJobResult>,\n )\n\n let remainingJobsFromQueried = 0\n for (const jobID in resultsObject) {\n const jobResult = resultsObject[jobID]\n if (jobResult?.status === 'error') {\n remainingJobsFromQueried++ // Can be retried\n }\n }\n\n return {\n jobStatus: resultsObject,\n remainingJobsFromQueried,\n }\n}\n"],"names":["v4","uuid","Forbidden","isolateObjectProperty","jobsCollectionSlug","JobCancelledError","JobRunAbortedError","getCurrentDate","updateJobs","startProcessingLeaseHeartbeat","getUpdateJobFunction","importHandlerPath","runJob","runJSONJob","runJobs","args","id","allQueues","limit","overrideAccess","processingOrder","queue","req","payload","config","jobs","jobsConfig","sequential","silent","where","whereFromProps","accessFn","access","run","hasAccess","t","now","duration","processingLeaseDuration","safetyBuffer","processingLeaseSafetyBuffer","processingLease","nowISOString","toISOString","processingUntil","Date","getTime","processingToken","and","completedAt","exists","hasError","not_equals","or","less_than_equal","waitUntil","less_than","push","equals","hasConcurrency","runningJobsWithConcurrency","db","find","collection","pagination","transactionID","undefined","select","concurrencyKey","greater_than","runningConcurrencyKeys","Set","docs","doc","add","size","not_in","updatedDocs","data","returning","defaultProcessingOrder","collections","defaultSort","processingOrderConfig","Array","isArray","queues","default","sort","length","noJobsRemaining","remainingJobsFromQueried","seenConcurrencyKeys","jobsToRun","jobsToRelease","job","has","releaseIds","map","in","info","newCount","retryCount","totalTried","logger","msg","new","retrying","successfullyCompletedJobs","runSingleJob","workflowSlug","taskSlug","Error","jobReq","workflowConfig","workflows","slug","tasks","taskExists","some","handler","input","errorMessage","error","updateJob","message","result","status","workflowHandler","jobLabel","cancelled","stopHeartbeat","jobIDs","resultsArray","jobPromises","Promise","all","filter","deleteJobOnComplete","deleteMany","err","join","resultsObject","reduce","acc","cur","jobID","jobResult","jobStatus"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJSONJob/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,4CAA4C,CAAA;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAOtD,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,GAAG,CAAA;IACR,GAAG,EAAE,cAAc,CAAA;IACnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,cAAc,EAAE,cAAc,CAAA;IAC9B,eAAe,EAAE,YAAY,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,YAAY,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,UAAU,sEAOpB,IAAI,KAAG,OAAO,CAAC,gBAAgB,CAwGjC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/queues/operations/runJobs/runJSONJob/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,4CAA4C,CAAA;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAOtD,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,GAAG,CAAA;IACR,GAAG,EAAE,cAAc,CAAA;IACnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,cAAc,EAAE,cAAc,CAAA;IAC9B,eAAe,EAAE,YAAY,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,YAAY,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,UAAU,sEAOpB,IAAI,KAAG,OAAO,CAAC,gBAAgB,CA4GjC,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { handleWorkflowError } from '../../../errors/handleWorkflowError.js';
2
- import { WorkflowError } from '../../../errors/index.js';
2
+ import { JobCancelledError, JobRunAbortedError, WorkflowError } from '../../../errors/index.js';
3
3
  import { getCurrentDate } from '../../../utilities/getCurrentDate.js';
4
4
  import { getRunTaskFunction } from '../runJob/getRunTaskFunction.js';
5
5
  export const runJSONJob = async ({ job, req, silent = false, updateJob, workflowConfig, workflowHandler })=>{
@@ -41,6 +41,9 @@ export const runJSONJob = async ({ job, req, silent = false, updateJob, workflow
41
41
  }
42
42
  }));
43
43
  } catch (error) {
44
+ if (error instanceof JobCancelledError || error instanceof JobRunAbortedError) {
45
+ throw error;
46
+ }
44
47
  const { hasFinalError } = await handleWorkflowError({
45
48
  error: error instanceof WorkflowError ? error : new WorkflowError({
46
49
  job,
@@ -77,14 +80,14 @@ export const runJSONJob = async ({ job, req, silent = false, updateJob, workflow
77
80
  if (workflowCompleted) {
78
81
  await updateJob({
79
82
  completedAt: getCurrentDate().toISOString(),
80
- processing: false,
83
+ processingUntil: null,
81
84
  totalTried: (job.totalTried ?? 0) + 1
82
85
  });
83
86
  return {
84
87
  status: 'success'
85
88
  };
86
89
  } else {
87
- // Retry the job - no need to bump processing or totalTried as this does not count as a retry. A condition of a different task might have just opened up!
90
+ // Retry the job - no need to bump processingUntil or totalTried as this does not count as a retry. A condition of a different task might have just opened up!
88
91
  return await runJSONJob({
89
92
  job,
90
93
  req,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJSONJob/index.ts"],"sourcesContent":["import type { Job } from '../../../../index.js'\nimport type { PayloadRequest } from '../../../../types/index.js'\nimport type { WorkflowJSON, WorkflowStep } from '../../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig } from '../../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../../localAPI.js'\nimport type { UpdateJobFunction } from '../runJob/getUpdateJobFunction.js'\nimport type { JobRunStatus } from '../runJob/index.js'\n\nimport { handleWorkflowError } from '../../../errors/handleWorkflowError.js'\nimport { WorkflowError } from '../../../errors/index.js'\nimport { getCurrentDate } from '../../../utilities/getCurrentDate.js'\nimport { getRunTaskFunction } from '../runJob/getRunTaskFunction.js'\n\ntype Args = {\n job: Job\n req: PayloadRequest\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n updateJob: UpdateJobFunction\n workflowConfig: WorkflowConfig\n workflowHandler: WorkflowJSON\n}\n\nexport type RunJSONJobResult = {\n status: JobRunStatus\n}\n\nexport const runJSONJob = async ({\n job,\n req,\n silent = false,\n updateJob,\n workflowConfig,\n workflowHandler,\n}: Args): Promise<RunJSONJobResult> => {\n const stepsToRun: WorkflowStep<string>[] = []\n\n for (const step of workflowHandler) {\n if ('task' in step) {\n if (job?.taskStatus?.[step.task]?.[step.id]?.complete) {\n continue\n }\n } else {\n if (job?.taskStatus?.['inline']?.[step.id]?.complete) {\n continue\n }\n }\n if (step.condition && !step.condition({ job })) {\n continue\n }\n stepsToRun.push(step)\n }\n\n const tasks = getRunTaskFunction(job, workflowConfig, req, false, updateJob)\n const inlineTask = getRunTaskFunction(job, workflowConfig, req, true, updateJob)\n\n // Run the job\n try {\n await Promise.all(\n stepsToRun.map(async (step) => {\n if ('task' in step) {\n await tasks[step.task]!(step.id, {\n input: step.input ? step.input({ job }) : {},\n retries: step.retries,\n })\n } else {\n await inlineTask(step.id, {\n retries: step.retries,\n task: step.inlineTask as any, // TODO: Fix type\n })\n }\n }),\n )\n } catch (error) {\n const { hasFinalError } = await handleWorkflowError({\n error:\n error instanceof WorkflowError\n ? error\n : new WorkflowError({\n job,\n message:\n typeof error === 'object' && error && 'message' in error\n ? (error.message as string)\n : 'An unhandled error occurred',\n workflowConfig,\n }),\n silent,\n\n req,\n updateJob,\n })\n\n return {\n status: hasFinalError ? 'error-reached-max-retries' : 'error',\n }\n }\n\n // Check if workflow has completed\n let workflowCompleted = false\n for (const [slug, map] of Object.entries(job.taskStatus)) {\n for (const [id, taskStatus] of Object.entries(map)) {\n if (taskStatus.complete) {\n const step = workflowHandler.find((step) => {\n if ('task' in step) {\n return step.task === slug && step.id === id\n } else {\n return step.id === id && slug === 'inline'\n }\n })\n if (step?.completesJob) {\n workflowCompleted = true\n break\n }\n }\n }\n }\n\n if (workflowCompleted) {\n await updateJob({\n completedAt: getCurrentDate().toISOString(),\n processing: false,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n status: 'success',\n }\n } else {\n // Retry the job - no need to bump processing or totalTried as this does not count as a retry. A condition of a different task might have just opened up!\n return await runJSONJob({\n job,\n req,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n }\n}\n"],"names":["handleWorkflowError","WorkflowError","getCurrentDate","getRunTaskFunction","runJSONJob","job","req","silent","updateJob","workflowConfig","workflowHandler","stepsToRun","step","taskStatus","task","id","complete","condition","push","tasks","inlineTask","Promise","all","map","input","retries","error","hasFinalError","message","status","workflowCompleted","slug","Object","entries","find","completesJob","completedAt","toISOString","processing","totalTried"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/queues/operations/runJobs/runJSONJob/index.ts"],"sourcesContent":["import type { Job } from '../../../../index.js'\nimport type { PayloadRequest } from '../../../../types/index.js'\nimport type { WorkflowJSON, WorkflowStep } from '../../../config/types/workflowJSONTypes.js'\nimport type { WorkflowConfig } from '../../../config/types/workflowTypes.js'\nimport type { RunJobsSilent } from '../../../localAPI.js'\nimport type { UpdateJobFunction } from '../runJob/getUpdateJobFunction.js'\nimport type { JobRunStatus } from '../runJob/index.js'\n\nimport { handleWorkflowError } from '../../../errors/handleWorkflowError.js'\nimport { JobCancelledError, JobRunAbortedError, WorkflowError } from '../../../errors/index.js'\nimport { getCurrentDate } from '../../../utilities/getCurrentDate.js'\nimport { getRunTaskFunction } from '../runJob/getRunTaskFunction.js'\n\ntype Args = {\n job: Job\n req: PayloadRequest\n /**\n * If set to true, the job system will not log any output to the console (for both info and error logs).\n * Can be an option for more granular control over logging.\n *\n * This will not automatically affect user-configured logs (e.g. if you call `console.log` or `payload.logger.info` in your job code).\n *\n * @default false\n */\n silent?: RunJobsSilent\n updateJob: UpdateJobFunction\n workflowConfig: WorkflowConfig\n workflowHandler: WorkflowJSON\n}\n\nexport type RunJSONJobResult = {\n status: JobRunStatus\n}\n\nexport const runJSONJob = async ({\n job,\n req,\n silent = false,\n updateJob,\n workflowConfig,\n workflowHandler,\n}: Args): Promise<RunJSONJobResult> => {\n const stepsToRun: WorkflowStep<string>[] = []\n\n for (const step of workflowHandler) {\n if ('task' in step) {\n if (job?.taskStatus?.[step.task]?.[step.id]?.complete) {\n continue\n }\n } else {\n if (job?.taskStatus?.['inline']?.[step.id]?.complete) {\n continue\n }\n }\n if (step.condition && !step.condition({ job })) {\n continue\n }\n stepsToRun.push(step)\n }\n\n const tasks = getRunTaskFunction(job, workflowConfig, req, false, updateJob)\n const inlineTask = getRunTaskFunction(job, workflowConfig, req, true, updateJob)\n\n // Run the job\n try {\n await Promise.all(\n stepsToRun.map(async (step) => {\n if ('task' in step) {\n await tasks[step.task]!(step.id, {\n input: step.input ? step.input({ job }) : {},\n retries: step.retries,\n })\n } else {\n await inlineTask(step.id, {\n retries: step.retries,\n task: step.inlineTask,\n })\n }\n }),\n )\n } catch (error) {\n if (error instanceof JobCancelledError || error instanceof JobRunAbortedError) {\n throw error\n }\n\n const { hasFinalError } = await handleWorkflowError({\n error:\n error instanceof WorkflowError\n ? error\n : new WorkflowError({\n job,\n message:\n typeof error === 'object' && error && 'message' in error\n ? (error.message as string)\n : 'An unhandled error occurred',\n workflowConfig,\n }),\n silent,\n\n req,\n updateJob,\n })\n\n return {\n status: hasFinalError ? 'error-reached-max-retries' : 'error',\n }\n }\n\n // Check if workflow has completed\n let workflowCompleted = false\n for (const [slug, map] of Object.entries(job.taskStatus)) {\n for (const [id, taskStatus] of Object.entries(map)) {\n if (taskStatus.complete) {\n const step = workflowHandler.find((step) => {\n if ('task' in step) {\n return step.task === slug && step.id === id\n } else {\n return step.id === id && slug === 'inline'\n }\n })\n if (step?.completesJob) {\n workflowCompleted = true\n break\n }\n }\n }\n }\n\n if (workflowCompleted) {\n await updateJob({\n completedAt: getCurrentDate().toISOString(),\n processingUntil: null,\n totalTried: (job.totalTried ?? 0) + 1,\n })\n\n return {\n status: 'success',\n }\n } else {\n // Retry the job - no need to bump processingUntil or totalTried as this does not count as a retry. A condition of a different task might have just opened up!\n return await runJSONJob({\n job,\n req,\n silent,\n updateJob,\n workflowConfig,\n workflowHandler,\n })\n }\n}\n"],"names":["handleWorkflowError","JobCancelledError","JobRunAbortedError","WorkflowError","getCurrentDate","getRunTaskFunction","runJSONJob","job","req","silent","updateJob","workflowConfig","workflowHandler","stepsToRun","step","taskStatus","task","id","complete","condition","push","tasks","inlineTask","Promise","all","map","input","retries","error","hasFinalError","message","status","workflowCompleted","slug","Object","entries","find","completesJob","completedAt","toISOString","processingUntil","totalTried"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import ObjectIdImport from 'bson-objectid';
2
- import { JobCancelledError, TaskError } from '../../../errors/index.js';
2
+ import { JobCancelledError, JobRunAbortedError, TaskError } from '../../../errors/index.js';
3
3
  import { getCurrentDate } from '../../../utilities/getCurrentDate.js';
4
4
  import { getTaskHandlerFromConfig } from './importHandlerPath.js';
5
5
  const ObjectId = 'default' in ObjectIdImport ? ObjectIdImport.default : ObjectIdImport;
@@ -75,8 +75,8 @@ export const getRunTaskFunction = (job, workflowConfig, req, isInline, updateJob
75
75
  })
76
76
  }))?.output;
77
77
  } catch (err) {
78
- if (err instanceof JobCancelledError) {
79
- // Re-throw JobCancelledError to be handled by the top-level error handler
78
+ if (err instanceof JobCancelledError || err instanceof JobRunAbortedError) {
79
+ // Job run aborts are handled by the top-level runner.
80
80
  throw err;
81
81
  }
82
82
  throw new TaskError({
@@ -106,9 +106,9 @@ export const getRunTaskFunction = (job, workflowConfig, req, isInline, updateJob
106
106
  id: new ObjectId().toHexString(),
107
107
  completedAt: getCurrentDate().toISOString(),
108
108
  executedAt: executedAt.toISOString(),
109
- input,
109
+ input: input ?? {},
110
110
  output,
111
- parent: jobConfig.addParentToTaskLog ? parent : undefined,
111
+ parent,
112
112
  state: 'succeeded',
113
113
  taskID,
114
114
  taskSlug