@squiz/job-runner-lib 2.2.0 → 2.4.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.
Files changed (137) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/domains/component/errors/JobError.spec.d.ts +1 -0
  3. package/lib/domains/job/ParsePartitionKey/ParsePartitionKey.d.ts +2 -2
  4. package/lib/domains/job/ParsePartitionKey/ParsePartitionKey.types.d.ts +5 -0
  5. package/lib/domains/job/S3Repository/JobDetailsRepository.d.ts +1 -2
  6. package/lib/domains/job/S3Repository/JobDetailsRepository.spec.d.ts +1 -1
  7. package/lib/domains/job/S3Repository/JobUploadsRepository.d.ts +16 -0
  8. package/lib/domains/job/{services/JobQueueService/JobQueueService.spec.d.ts → S3Repository/JobUploadsRepository.spec.d.ts} +1 -1
  9. package/lib/domains/job/S3Repository/S3RepositoryBase.d.ts +12 -5
  10. package/lib/domains/job/S3Repository/index.d.ts +2 -1
  11. package/lib/domains/job/constants/InjectTokens.d.ts +8 -0
  12. package/lib/domains/job/constants/JobExecutionStatus.constants.d.ts +2 -1
  13. package/lib/domains/job/constants/Repository.constants.d.ts +3 -3
  14. package/lib/domains/job/constants/RetryConfig.constants.d.ts +21 -0
  15. package/lib/domains/job/index.d.ts +6 -4
  16. package/lib/domains/job/manifest/JobManifestTypes.d.ts +7 -6
  17. package/lib/domains/job/model/Base/Base.d.ts +10 -5
  18. package/lib/domains/job/model/Job/Job.d.ts +9 -6
  19. package/lib/domains/job/model/JobContext/JobContext.d.ts +6 -5
  20. package/lib/domains/job/model/JobExecution/JobExecution.d.ts +64 -9
  21. package/lib/domains/job/model/LogPayload/LogPayload.d.ts +21 -12
  22. package/lib/domains/job/model/LogPayload/index.d.ts +1 -0
  23. package/lib/domains/job/model/LogPayload/mocks/LogPayload.mock.d.ts +6 -0
  24. package/lib/domains/job/repository/AbstractRepository.d.ts +20 -11
  25. package/lib/domains/job/repository/JobContextRepository/JobContextRepository.d.ts +6 -7
  26. package/lib/domains/job/repository/JobExecutionRepository/JobExecutionRepository.d.ts +7 -17
  27. package/lib/domains/job/repository/JobExecutionRepository/JobExecutionRepository.spec.d.ts +1 -1
  28. package/lib/domains/job/repository/JobExecutionRepository/utils/convertDynamoDbItemToJobExecution/convertDynamoDbItemToJobExecution.d.ts +2 -0
  29. package/lib/domains/job/repository/JobExecutionRepository/utils/index.d.ts +1 -0
  30. package/lib/domains/job/repository/JobManifestRepository/JobManifestRepository.d.ts +5 -6
  31. package/lib/domains/job/repository/JobRepository/JobRepository.d.ts +6 -7
  32. package/lib/domains/job/repository/MultiTenantJobExecutionRepository/MultiTenantJobExecutionRepository.d.ts +9 -0
  33. package/lib/domains/job/repository/MultiTenantJobExecutionRepository/MultiTenantJobExecutionRepository.spec.d.ts +1 -0
  34. package/lib/domains/job/repository/index.d.ts +1 -0
  35. package/lib/domains/job/services/JobContextService/JobContextService.d.ts +6 -3
  36. package/lib/domains/job/services/JobExecutionTaskService/JobExecutionTaskService.d.ts +10 -6
  37. package/lib/domains/job/services/JobExecutionTaskService/JobExecutionTaskService.defs.d.ts +1 -3
  38. package/lib/domains/job/services/JobManifestService/JobManifestService.d.ts +0 -1
  39. package/lib/domains/job/services/JobStartQueueService/JobStartQueueService.d.ts +17 -0
  40. package/lib/domains/job/services/JobStartQueueService/JobStartQueueService.defs.d.ts +25 -0
  41. package/lib/domains/job/services/JobUploadService/utils/manifestValidator.d.ts +1 -2
  42. package/lib/domains/job/services/index.d.ts +2 -1
  43. package/lib/domains/manifest/services/ManifestServiceForDev.d.ts +0 -3
  44. package/lib/index.d.ts +1 -0
  45. package/lib/index.js +13 -13
  46. package/lib/index.js.map +4 -4
  47. package/lib/jest-global-setup.d.ts +6 -1
  48. package/lib/mocks/mockIoc.d.ts +3 -3
  49. package/lib/utils/buildJobRunnerModule/buildJobRunnerModule.d.ts +2 -0
  50. package/lib/utils/buildJobRunnerModule/buildJobRunnerModule.types.d.ts +14 -0
  51. package/lib/utils/index.d.ts +2 -0
  52. package/package.json +12 -11
  53. package/src/domains/component/errors/JobError.spec.ts +30 -0
  54. package/src/domains/component/errors/JobError.ts +8 -1
  55. package/src/domains/job/ParsePartitionKey/ParsePartitionKey.spec.ts +17 -8
  56. package/src/domains/job/ParsePartitionKey/ParsePartitionKey.ts +13 -16
  57. package/src/domains/job/ParsePartitionKey/ParsePartitionKey.types.ts +6 -0
  58. package/src/domains/job/S3Repository/JobDetailsRepository.spec.ts +47 -31
  59. package/src/domains/job/S3Repository/JobDetailsRepository.ts +7 -8
  60. package/src/domains/job/S3Repository/JobUploadsRepository.spec.ts +66 -0
  61. package/src/domains/job/S3Repository/JobUploadsRepository.ts +35 -0
  62. package/src/domains/job/S3Repository/S3RepositoryBase.spec.ts +13 -19
  63. package/src/domains/job/S3Repository/S3RepositoryBase.ts +24 -9
  64. package/src/domains/job/S3Repository/index.ts +2 -1
  65. package/src/domains/job/constants/InjectTokens.ts +8 -0
  66. package/src/domains/job/constants/JobExecutionStatus.constants.ts +1 -0
  67. package/src/domains/job/constants/Repository.constants.ts +3 -3
  68. package/src/domains/job/constants/RetryConfig.constants.ts +29 -0
  69. package/src/domains/job/core/pagination/services/PaginationService.spec.ts +3 -5
  70. package/src/domains/job/index.ts +6 -4
  71. package/src/domains/job/manifest/JobManifestTypes.ts +8 -6
  72. package/src/domains/job/manifest/mocks/JobManifest.mock.ts +2 -2
  73. package/src/domains/job/manifest/mocks/JobManifestDto.mock.ts +3 -2
  74. package/src/domains/job/manifest/mocks/JobManifestRecord.mock.ts +4 -3
  75. package/src/domains/job/model/Base/Base.ts +11 -5
  76. package/src/domains/job/model/Job/Job.ts +11 -6
  77. package/src/domains/job/model/Job/mocks/Job.mock.ts +2 -2
  78. package/src/domains/job/model/Job/mocks/JobDto.mock.ts +3 -2
  79. package/src/domains/job/model/Job/mocks/JobRecord.mock.ts +3 -2
  80. package/src/domains/job/model/JobContext/JobContext.ts +7 -5
  81. package/src/domains/job/model/JobContext/mocks/JobContext.mock.ts +2 -2
  82. package/src/domains/job/model/JobContext/mocks/JobContextDto.mock.ts +3 -2
  83. package/src/domains/job/model/JobContext/mocks/JobContextRecord.mock.ts +3 -2
  84. package/src/domains/job/model/JobExecution/JobExecution.ts +74 -9
  85. package/src/domains/job/model/JobExecution/mocks/JobExecution.mock.ts +7 -4
  86. package/src/domains/job/model/JobExecution/mocks/JobExecutionDto.mock.ts +32 -16
  87. package/src/domains/job/model/JobExecution/mocks/JobExecutionRecord.mock.ts +10 -4
  88. package/src/domains/job/model/LogPayload/LogPayload.ts +32 -11
  89. package/src/domains/job/model/LogPayload/index.ts +1 -0
  90. package/src/domains/job/model/LogPayload/mocks/LogPayload.mock.ts +21 -0
  91. package/src/domains/job/repository/AbstractRepository.ts +91 -59
  92. package/src/domains/job/repository/JobContextRepository/JobContextRepository.spec.ts +39 -49
  93. package/src/domains/job/repository/JobContextRepository/JobContextRepository.ts +33 -21
  94. package/src/domains/job/repository/JobExecutionRepository/JobExecutionRepository.spec.ts +343 -169
  95. package/src/domains/job/repository/JobExecutionRepository/JobExecutionRepository.ts +112 -141
  96. package/src/domains/job/repository/JobExecutionRepository/utils/convertDynamoDbItemToJobExecution/convertDynamoDbItemToJobExecution.ts +22 -0
  97. package/src/domains/job/repository/JobExecutionRepository/utils/index.ts +1 -0
  98. package/src/domains/job/repository/JobManifestRepository/JobManifestRepository.spec.ts +23 -38
  99. package/src/domains/job/repository/JobManifestRepository/JobManifestRepository.ts +29 -36
  100. package/src/domains/job/repository/JobRepository/JobRepository.spec.ts +72 -80
  101. package/src/domains/job/repository/JobRepository/JobRepository.ts +66 -70
  102. package/src/domains/job/repository/MultiTenantJobExecutionRepository/MultiTenantJobExecutionRepository.spec.ts +60 -0
  103. package/src/domains/job/repository/MultiTenantJobExecutionRepository/MultiTenantJobExecutionRepository.ts +42 -0
  104. package/src/domains/job/repository/index.ts +1 -0
  105. package/src/domains/job/services/JobContextService/JobContextService.spec.ts +73 -39
  106. package/src/domains/job/services/JobContextService/JobContextService.ts +37 -6
  107. package/src/domains/job/services/JobExecutionTaskService/JobExecutionTaskService.defs.ts +1 -3
  108. package/src/domains/job/services/JobExecutionTaskService/JobExecutionTaskService.spec.ts +113 -31
  109. package/src/domains/job/services/JobExecutionTaskService/JobExecutionTaskService.ts +101 -49
  110. package/src/domains/job/services/JobManifestService/JobManifestService.spec.ts +4 -41
  111. package/src/domains/job/services/JobManifestService/JobManifestService.ts +2 -8
  112. package/src/domains/job/services/JobStartQueueService/JobStartQueueService.defs.ts +27 -0
  113. package/src/domains/job/services/JobStartQueueService/JobStartQueueService.ts +42 -0
  114. package/src/domains/job/services/JobUploadService/JobUploadService.spec.ts +1 -1
  115. package/src/domains/job/services/JobUploadService/JobUploadService.ts +1 -1
  116. package/src/domains/job/services/JobUploadService/utils/manifestValidator.spec.ts +12 -25
  117. package/src/domains/job/services/JobUploadService/utils/manifestValidator.ts +2 -7
  118. package/src/domains/job/services/index.ts +2 -1
  119. package/src/domains/job/utils/SlackClient/SlackClient.spec.ts +0 -2
  120. package/src/domains/manifest/services/ManifestServiceForDev.spec.ts +1 -2
  121. package/src/domains/manifest/services/ManifestServiceForDev.ts +0 -4
  122. package/src/index.ts +1 -0
  123. package/src/jest-global-setup.ts +8 -4
  124. package/src/mocks/mockIoc.ts +18 -43
  125. package/src/utils/buildJobRunnerModule/buildJobRunnerModule.ts +81 -0
  126. package/src/utils/buildJobRunnerModule/buildJobRunnerModule.types.ts +13 -0
  127. package/src/utils/index.ts +2 -0
  128. package/lib/domains/job/S3Repository/S3Repository.d.ts +0 -15
  129. package/lib/domains/job/S3Repository/S3Repository.spec.d.ts +0 -5
  130. package/lib/domains/job/services/JobQueueService/JobQueueService.d.ts +0 -9
  131. package/lib/domains/job/services/JobQueueService/JobQueueService.defs.d.ts +0 -9
  132. package/src/custom-types.d.ts +0 -7
  133. package/src/domains/job/S3Repository/S3Repository.spec.ts +0 -50
  134. package/src/domains/job/S3Repository/S3Repository.ts +0 -27
  135. package/src/domains/job/services/JobQueueService/JobQueueService.defs.ts +0 -10
  136. package/src/domains/job/services/JobQueueService/JobQueueService.spec.ts +0 -190
  137. package/src/domains/job/services/JobQueueService/JobQueueService.ts +0 -60
@@ -0,0 +1,29 @@
1
+ /*!
2
+ * @license
3
+ * Copyright Squiz Australia Pty Ltd. All Rights Reserved.
4
+ */
5
+
6
+ /**
7
+ * Retry configuration with exponential backoff delays in seconds.
8
+ * Using SQS message timer limits (max 15 minutes = 900 seconds).
9
+ *
10
+ * Delays: 30s, 1min, 2min, 5min, 10min, 15min
11
+ */
12
+ export const RETRY_DELAYS_SECONDS: ReadonlyArray<number> = [30, 60, 120, 300, 600, 900];
13
+
14
+ /**
15
+ * Maximum number of retry attempts for container start failures.
16
+ */
17
+ export const MAX_RETRY_ATTEMPTS = RETRY_DELAYS_SECONDS.length;
18
+
19
+ /**
20
+ * Get the delay in seconds for a given retry attempt.
21
+ * @param retryAttempt - The current retry attempt (0-indexed)
22
+ * @returns The delay in seconds for this retry attempt
23
+ */
24
+ export const getRetryDelaySeconds = (retryAttempt: number): number => {
25
+ if (retryAttempt >= RETRY_DELAYS_SECONDS.length) {
26
+ return RETRY_DELAYS_SECONDS[RETRY_DELAYS_SECONDS.length - 1];
27
+ }
28
+ return RETRY_DELAYS_SECONDS[retryAttempt];
29
+ };
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { AttributeValue } from '@aws-sdk/client-dynamodb';
7
7
  import { faker } from '@faker-js/faker/locale/en';
8
- import { PartitionKey, PARTITION_KEYS } from '../../../constants/Repository.constants';
8
+ import { EntityType, ENTITY_TYPES } from '../../../constants/Repository.constants';
9
9
  import { PaginationInfo } from '../model/PaginationInfo';
10
10
  import { PAGINATION_DIRECTION_TYPE_AFTER, PAGINATION_DIRECTION_TYPE_BEFORE } from '../model/PaginationTypes';
11
11
  import { encodeTokenString } from '../utils/PaginationUtils';
@@ -20,16 +20,14 @@ describe('PaginationService', (): void => {
20
20
  });
21
21
 
22
22
  describe('addPaginationLinksToResponse', (): void => {
23
- let mockType: PartitionKey;
23
+ let mockType: EntityType;
24
24
  let mockData;
25
25
  let mockPaginationInfo: PaginationInfo;
26
26
  let mockExclusiveStartKey: Record<string, AttributeValue>;
27
27
  const mockLastEvaluatedKey: string | null = null;
28
28
 
29
29
  beforeEach(() => {
30
- jest.resetAllMocks();
31
-
32
- mockType = PARTITION_KEYS.job;
30
+ mockType = ENTITY_TYPES.job;
33
31
 
34
32
  mockPaginationInfo = {
35
33
  direction: PAGINATION_DIRECTION_TYPE_AFTER,
@@ -1,23 +1,25 @@
1
- export * from './core/pagination';
2
1
  export * from './core/dynamoClient.mock';
2
+ export * from './core/pagination';
3
3
 
4
+ export * from './constants/InjectTokens';
4
5
  export * from './constants/JobExecutionStatus.constants';
5
6
  export * from './constants/Repository.constants';
7
+ export * from './constants/RetryConfig.constants';
6
8
 
7
9
  export * from './services';
8
10
  export * from './utils';
9
11
 
12
+ export * from './model/Base';
10
13
  export * from './model/Job';
11
14
  export * from './model/JobContext';
12
15
  export * from './model/JobExecution';
13
- export * from './model/Base';
14
16
  export * from './model/LogPayload';
15
17
 
16
18
  export * from './errors';
17
19
  export * from './manifest';
18
20
  export * from './ParsePartitionKey';
19
21
 
20
- export * from './transientProvider';
21
- export * from './singletonProvider';
22
22
  export * from './repository';
23
23
  export * from './S3Repository';
24
+ export * from './singletonProvider';
25
+ export * from './transientProvider';
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { AttributeValue } from '@aws-sdk/client-dynamodb';
7
7
  import { MANIFEST_MODELS } from '@squiz/dx-json-schema-lib';
8
- import { PartitionKey } from '../constants/Repository.constants';
8
+ import { EntityType } from '../constants/Repository.constants';
9
9
 
10
10
  /**
11
11
  * Job manifest interface.
@@ -59,10 +59,10 @@ export interface JobManifest {
59
59
 
60
60
  /**
61
61
  * The DynamoDB record type ('job').
62
- * @type {PartitionKey}
62
+ * @type {EntityType}
63
63
  * @memberof JobManifest
64
64
  */
65
- type: PartitionKey;
65
+ type: EntityType;
66
66
  }
67
67
 
68
68
  /**
@@ -73,10 +73,10 @@ export interface JobManifest {
73
73
  export interface JobManifestRecord {
74
74
  /**
75
75
  * The partition key ('manifest').
76
- * @type {PartitionKey}
76
+ * @type {EntityType}
77
77
  * @memberof JobManifestRecord
78
78
  */
79
- pk: PartitionKey;
79
+ pk: EntityType;
80
80
 
81
81
  /**
82
82
  * The sort key ('name-version').
@@ -142,4 +142,6 @@ export type CreateJobManifestRequest = Omit<JobManifest, 'type'>;
142
142
  * The request body for updating a job (PUT /job-manifest).
143
143
  * @export
144
144
  */
145
- export type UpdateJobManifestRequest = Partial<Omit<JobManifest, 'name' | 'type'>>;
145
+ export type UpdateJobManifestRequest = Partial<Omit<JobManifest, 'name' | 'version' | 'type'>>;
146
+
147
+ export type JobManifestSk = Pick<JobManifest, 'name' | 'version'>;
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../constants/Repository.constants';
8
8
  import { JobManifest } from '../JobManifestTypes';
9
9
 
10
10
  export const createMockJobManifest = (partialRecord: Partial<JobManifest> = {}): JobManifest => {
@@ -24,7 +24,7 @@ export const createMockJobManifest = (partialRecord: Partial<JobManifest> = {}):
24
24
  name: faker.lorem.word(),
25
25
  version,
26
26
  timeoutSeconds: faker.number.int({ max: 28800, min: 5 }),
27
- type: PARTITION_KEYS.job,
27
+ type: ENTITY_TYPES.manifest,
28
28
  ...partialRecord,
29
29
  };
30
30
  };
@@ -4,10 +4,11 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../constants/Repository.constants';
8
8
  import { JobManifestDto, JobManifestRecord } from '../JobManifestTypes';
9
9
 
10
10
  export const createMockJobManifestDto = (partialRecord: Partial<JobManifestRecord> = {}): JobManifestDto => {
11
+ const tenant = faker.string.uuid();
11
12
  const name = faker.lorem.word();
12
13
  const version = Array.from({ length: 3 })
13
14
  .map(() => faker.number.int())
@@ -23,7 +24,7 @@ export const createMockJobManifestDto = (partialRecord: Partial<JobManifestRecor
23
24
  S: JSON.stringify(partialRecord.entryFunction) ?? JSON.stringify(input),
24
25
  },
25
26
  pk: {
26
- S: partialRecord.pk ?? PARTITION_KEYS.manifest,
27
+ S: partialRecord.pk ?? `${ENTITY_TYPES.manifest}~${tenant}`,
27
28
  },
28
29
  sk: {
29
30
  S: partialRecord.sk ?? `${name}-${version}`,
@@ -4,10 +4,11 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../constants/Repository.constants';
8
8
  import { JobManifestRecord } from '../JobManifestTypes';
9
9
 
10
10
  export const createMockJobManifestRecord = (partialRecord: Partial<JobManifestRecord> = {}): JobManifestRecord => {
11
+ const tenant = faker.string.uuid();
11
12
  const name = faker.lorem.word();
12
13
  const version = Array.from({ length: 3 })
13
14
  .map(() => faker.number.int())
@@ -22,8 +23,8 @@ export const createMockJobManifestRecord = (partialRecord: Partial<JobManifestRe
22
23
  entry: faker.system.filePath(),
23
24
  input,
24
25
  },
25
- pk: PARTITION_KEYS.job,
26
- sk: `${name}-${version}`,
26
+ pk: `${ENTITY_TYPES.manifest}~${tenant}`,
27
+ sk: `${name}~${version}`,
27
28
  name,
28
29
  version,
29
30
  timeoutSeconds: faker.number.int({ max: 28800, min: 5 }),
@@ -1,5 +1,5 @@
1
1
  import { AttributeValue } from '@aws-sdk/client-dynamodb';
2
- import { PartitionKey } from '../../constants/Repository.constants';
2
+ import { EntityType } from '../../constants/Repository.constants';
3
3
 
4
4
  /**
5
5
  * The base interface for job runner entities.
@@ -9,10 +9,10 @@ import { PartitionKey } from '../../constants/Repository.constants';
9
9
  export interface BaseItem {
10
10
  /**
11
11
  * The property representing the corresponding record's partition key.
12
- * @type {PartitionKey}
12
+ * @type {EntityType}
13
13
  * @memberof BaseItem
14
14
  */
15
- type: PartitionKey;
15
+ type: EntityType;
16
16
  }
17
17
 
18
18
  /**
@@ -23,10 +23,10 @@ export interface BaseItem {
23
23
  export interface BaseRecord {
24
24
  /**
25
25
  * The partition key.
26
- * @type {PartitionKey}
26
+ * @type {EntityType}
27
27
  * @memberof BaseRecord
28
28
  */
29
- pk: PartitionKey;
29
+ pk: EntityType;
30
30
 
31
31
  /**
32
32
  * The sort key.
@@ -42,3 +42,9 @@ export interface BaseRecord {
42
42
  * @interface BaseDto
43
43
  */
44
44
  export type BaseDto = Record<keyof BaseRecord, AttributeValue>;
45
+
46
+ export type ListParameters<TFilters> = {
47
+ filters?: TFilters;
48
+ consistentRead?: boolean;
49
+ limit?: number;
50
+ };
@@ -4,7 +4,8 @@
4
4
  */
5
5
 
6
6
  import { AttributeValue } from '@aws-sdk/client-dynamodb';
7
- import { PartitionKey } from '../../constants/Repository.constants';
7
+ import { EntityType } from '../../constants/Repository.constants';
8
+ import { ListParameters } from '../Base';
8
9
 
9
10
  /**
10
11
  * Job interface.
@@ -35,10 +36,10 @@ export interface Job {
35
36
 
36
37
  /**
37
38
  * The DynamoDB record type ('job').
38
- * @type {PartitionKey}
39
+ * @type {EntityType}
39
40
  * @memberof Job
40
41
  */
41
- type: PartitionKey;
42
+ type: EntityType;
42
43
  }
43
44
 
44
45
  /**
@@ -49,10 +50,10 @@ export interface Job {
49
50
  export interface JobRecord {
50
51
  /**
51
52
  * The partition key ('job').
52
- * @type {PartitionKey}
53
+ * @type {EntityType}
53
54
  * @memberof JobRecord
54
55
  */
55
- pk: PartitionKey;
56
+ pk: EntityType;
56
57
 
57
58
  /**
58
59
  * The sort key ('name-version').
@@ -89,10 +90,14 @@ export type JobDto = Record<keyof JobRecord, AttributeValue>;
89
90
  * The parameters for listing jobs.
90
91
  * @export
91
92
  */
92
- export type ListJobParameters = Partial<Pick<Job, 'name' | 'version'>>;
93
+ export type ListJobParameters = ListParameters<Partial<Pick<Job, 'name' | 'version'>>>;
93
94
 
94
95
  /**
95
96
  * The request body for creating a job (POST /job).
96
97
  * @export
97
98
  */
98
99
  export type CreateJobRequest = Omit<Job, 'type'>;
100
+
101
+ export type UpdateJobRequest = Partial<Omit<Job, 'name' | 'version' | 'type'>>;
102
+
103
+ export type JobSk = Pick<Job, 'name' | 'version'>;
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../../constants/Repository.constants';
8
8
  import { Job } from '../Job';
9
9
 
10
10
  export const createMockJob = (partialRecord: Partial<Job> = {}): Job => {
@@ -14,7 +14,7 @@ export const createMockJob = (partialRecord: Partial<Job> = {}): Job => {
14
14
  return {
15
15
  name: faker.lorem.word(),
16
16
  description: faker.lorem.sentence(),
17
- type: PARTITION_KEYS.job,
17
+ type: ENTITY_TYPES.job,
18
18
  version: version,
19
19
  ...partialRecord,
20
20
  };
@@ -4,17 +4,18 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../../constants/Repository.constants';
8
8
  import { JobDto, JobRecord } from '../Job';
9
9
 
10
10
  export const createMockJobDto = (partialRecord: Partial<JobRecord> = {}): JobDto => {
11
+ const tenant = faker.string.uuid();
11
12
  const version = Array.from({ length: 3 })
12
13
  .map(() => faker.number.int())
13
14
  .join('.');
14
15
 
15
16
  return {
16
17
  pk: {
17
- S: partialRecord.pk ?? PARTITION_KEYS.job,
18
+ S: partialRecord.pk ?? `${ENTITY_TYPES.job}~${tenant}`,
18
19
  },
19
20
  sk: {
20
21
  S: partialRecord.sk ?? `${faker.lorem.word()}-${faker.lorem.word()}`,
@@ -4,16 +4,17 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../../constants/Repository.constants';
8
8
  import { JobRecord } from '../Job';
9
9
 
10
10
  export const createMockJobRecord = (partialRecord: Partial<JobRecord> = {}): JobRecord => {
11
+ const tenant = faker.string.uuid();
11
12
  const version = Array.from({ length: 3 })
12
13
  .map(() => faker.number.int())
13
14
  .join('.');
14
15
 
15
16
  return {
16
- pk: PARTITION_KEYS.job,
17
+ pk: `${ENTITY_TYPES.job}~${tenant}`,
17
18
  sk: `${faker.lorem.word()}-${faker.lorem.word()}`,
18
19
  name: faker.lorem.word(),
19
20
  description: faker.lorem.sentence(),
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { AttributeValue } from '@aws-sdk/client-dynamodb';
7
- import { PartitionKey } from '../../constants/Repository.constants';
7
+ import { EntityType } from '../../constants/Repository.constants';
8
8
 
9
9
  /**
10
10
  * Environment interface.
@@ -45,10 +45,10 @@ export interface JobContext {
45
45
 
46
46
  /**
47
47
  * The DynamoDB record type ('context').
48
- * @type {PartitionKey}
48
+ * @type {EntityType}
49
49
  * @memberof JobContext
50
50
  */
51
- type: PartitionKey;
51
+ type: EntityType;
52
52
  }
53
53
 
54
54
  /**
@@ -59,10 +59,10 @@ export interface JobContext {
59
59
  export interface JobContextRecord {
60
60
  /**
61
61
  * The partition key ('context').
62
- * @type {PartitionKey}
62
+ * @type {EntityType}
63
63
  * @memberof JobContextRecord
64
64
  */
65
- pk: PartitionKey;
65
+ pk: EntityType;
66
66
 
67
67
  /**
68
68
  * The description of the job context.
@@ -99,3 +99,5 @@ export type CreateJobContextRequest = Omit<JobContext, 'type'>;
99
99
  * @export
100
100
  */
101
101
  export type UpdateJobContextRequest = Partial<Omit<JobContext, 'contextName' | 'type'>>;
102
+
103
+ export type JobContextSk = Pick<JobContext, 'contextName'>;
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../../constants/Repository.constants';
8
8
  import { JobContext } from '../JobContext';
9
9
 
10
10
  export const createMockJobContext = (partialRecord: Partial<JobContext> = {}): JobContext => {
@@ -23,7 +23,7 @@ export const createMockJobContext = (partialRecord: Partial<JobContext> = {}): J
23
23
  contextName: faker.lorem.word(),
24
24
  description: faker.lorem.words(),
25
25
  environment,
26
- type: PARTITION_KEYS.context,
26
+ type: ENTITY_TYPES.context,
27
27
  ...partialRecord,
28
28
  };
29
29
  };
@@ -4,10 +4,11 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../../constants/Repository.constants';
8
8
  import { JobContextDto, JobContextRecord } from '../JobContext';
9
9
 
10
10
  export const createMockJobContextDto = (partialRecord: Partial<JobContextRecord> = {}): JobContextDto => {
11
+ const tenant = faker.string.uuid();
11
12
  const environment: Record<string, string> = partialRecord.environment ?? {};
12
13
 
13
14
  if (!partialRecord.environment) {
@@ -32,7 +33,7 @@ export const createMockJobContextDto = (partialRecord: Partial<JobContextRecord>
32
33
  S: partialRecord.description ?? faker.lorem.words(),
33
34
  },
34
35
  pk: {
35
- S: partialRecord.pk ?? PARTITION_KEYS.context,
36
+ S: partialRecord.pk ?? `${ENTITY_TYPES.context}~${tenant}`,
36
37
  },
37
38
  sk: {
38
39
  S: partialRecord.sk ?? faker.lorem.word(),
@@ -4,10 +4,11 @@
4
4
  */
5
5
 
6
6
  import { faker } from '@faker-js/faker/locale/en';
7
- import { PARTITION_KEYS } from '../../../constants/Repository.constants';
7
+ import { ENTITY_TYPES } from '../../../constants/Repository.constants';
8
8
  import { JobContextRecord } from '../JobContext';
9
9
 
10
10
  export const createMockJobContextRecord = (partialRecord: Partial<JobContextRecord> = {}): JobContextRecord => {
11
+ const tenant = faker.string.uuid();
11
12
  const contextName = faker.lorem.word();
12
13
  const numOfEnvVars = faker.number.int({ max: 5, min: 1 });
13
14
  const environment: Record<string, string> = {};
@@ -20,7 +21,7 @@ export const createMockJobContextRecord = (partialRecord: Partial<JobContextReco
20
21
  return {
21
22
  environment,
22
23
  description,
23
- pk: PARTITION_KEYS.context,
24
+ pk: `${ENTITY_TYPES.context}~${tenant}`,
24
25
  sk: contextName,
25
26
  ...partialRecord,
26
27
  };
@@ -3,9 +3,9 @@
3
3
  * Copyright Squiz Australia Pty Ltd. All Rights Reserved.
4
4
  */
5
5
 
6
- import { JobExecutionStatus } from '../../constants/JobExecutionStatus.constants';
7
- import { JobExecutionPk } from '../../constants/Repository.constants';
8
6
  import { AttributeValue } from '@aws-sdk/client-dynamodb';
7
+ import { JobExecutionStatus } from '../../constants/JobExecutionStatus.constants';
8
+ import { ListParameters } from '../Base';
9
9
 
10
10
  /**
11
11
  * JobExecution interface.
@@ -85,10 +85,32 @@ export interface JobExecution {
85
85
 
86
86
  /**
87
87
  * The DynamoDB record type (dynamic, 'jobExecution-<jobName>').
88
- * @type {JobExecutionPk}
88
+ * @type {string}
89
+ * @memberof JobExecution
90
+ */
91
+ type: string;
92
+
93
+ /**
94
+ * The number of times the container start has been retried.
95
+ * @type {number}
96
+ * @memberof JobExecution
97
+ */
98
+ retryCount: number;
99
+
100
+ /**
101
+ * The reason for the last container start failure (if any).
102
+ * @type {(string | null)}
89
103
  * @memberof JobExecution
90
104
  */
91
- type: JobExecutionPk;
105
+ lastFailureReason: string | null;
106
+
107
+ /**
108
+ * ISO timestamp indicating when the execution can be retried.
109
+ * Used to implement exponential backoff - executions with retryAfter > now should be skipped.
110
+ * @type {(string | null)}
111
+ * @memberof JobExecution
112
+ */
113
+ retryAfter: string | null;
92
114
  }
93
115
 
94
116
  /**
@@ -98,19 +120,33 @@ export interface JobExecution {
98
120
  */
99
121
  export interface JobExecutionRecord {
100
122
  /**
101
- * The partition key (dynamic, 'jobExecution-<jobName>').
102
- * @type {JobExecutionPk}
123
+ * The partition key ('jobExecution~<tenant>').
124
+ * @type {string}
103
125
  * @memberof JobExecutionRecord
104
126
  */
105
- pk: JobExecutionPk;
127
+ pk: string;
106
128
 
107
129
  /**
108
- * The sort key ('timeQueued-id').
130
+ * The sort key ('<jobName>~<id>').
109
131
  * @type {string}
110
132
  * @memberof JobExecutionRecord
111
133
  */
112
134
  sk: string;
113
135
 
136
+ /**
137
+ * Secondary sort key ('<status>~<jobName>').
138
+ * @type {string}
139
+ * @memberof JobExecutionRecord
140
+ */
141
+ lsi1sk: string;
142
+
143
+ /**
144
+ * Global secondary partition key ('jobExecution~<status>').
145
+ * @type {string}
146
+ * @memberof JobExecutionRecord
147
+ */
148
+ gsi1pk: string;
149
+
114
150
  /**
115
151
  * The name of the job to execute.
116
152
  * @type {string}
@@ -180,6 +216,28 @@ export interface JobExecutionRecord {
180
216
  * @memberof JobExecutionRecord
181
217
  */
182
218
  input: any;
219
+
220
+ /**
221
+ * The number of times the container start has been retried.
222
+ * @type {number}
223
+ * @memberof JobExecutionRecord
224
+ */
225
+ retryCount: number;
226
+
227
+ /**
228
+ * The reason for the last container start failure (if any).
229
+ * @type {(string | null)}
230
+ * @memberof JobExecutionRecord
231
+ */
232
+ lastFailureReason: string | null;
233
+
234
+ /**
235
+ * ISO timestamp indicating when the execution can be retried.
236
+ * Used to implement exponential backoff - executions with retryAfter > now should be skipped.
237
+ * @type {(string | null)}
238
+ * @memberof JobExecutionRecord
239
+ */
240
+ retryAfter: string | null;
183
241
  }
184
242
 
185
243
  export type JobExecutionDto = Record<keyof JobExecutionRecord, AttributeValue>;
@@ -211,10 +269,17 @@ export interface TerminateJobExecutionRequest {
211
269
  * The parameters for listing job executions.
212
270
  * @export
213
271
  */
214
- export type ListJobExecutionParameters = Partial<Pick<JobExecution, 'jobName' | 'status'>>;
272
+ export type ListJobExecutionParameters = ListParameters<Partial<Pick<JobExecution, 'jobName' | 'status'>>>;
215
273
 
216
274
  /**
217
275
  * The parameters for updating job executions.
218
276
  * @export
219
277
  */
220
278
  export type UpdateJobExecutionParameters = Partial<Omit<JobExecution, 'id' | 'jobName' | 'timeQueued' | 'type'>>;
279
+
280
+ export type JobExecutionSk = Pick<JobExecution, 'jobName' | 'id'>;
281
+
282
+ /**
283
+ * Array of job executions keys by tenant.
284
+ */
285
+ export type JobExecutionsByTenant = Record<string, Array<JobExecution>>;
@@ -3,9 +3,9 @@
3
3
  * Copyright Squiz Australia Pty Ltd. All Rights Reserved.
4
4
  */
5
5
 
6
- import { JOB_EXECUTION_STATUS } from '../../../constants/JobExecutionStatus.constants';
7
- import { PARTITION_KEYS } from '../../../constants/Repository.constants';
8
6
  import { faker } from '@faker-js/faker/locale/en';
7
+ import { JOB_EXECUTION_STATUS } from '../../../constants/JobExecutionStatus.constants';
8
+ import { ENTITY_TYPES } from '../../../constants/Repository.constants';
9
9
  import { JobExecution } from '../JobExecution';
10
10
 
11
11
  export const createMockJobExecution = (partialRecord: Partial<JobExecution> = {}): JobExecution => {
@@ -19,7 +19,7 @@ export const createMockJobExecution = (partialRecord: Partial<JobExecution> = {}
19
19
  { [faker.lorem.word()]: faker.lorem.words() },
20
20
  null,
21
21
  ]);
22
- const jobName = faker.lorem.word();
22
+ const jobName = partialRecord.jobName || faker.lorem.word();
23
23
  const timeQueued = new Date().toISOString();
24
24
  return {
25
25
  context: faker.string.uuid(),
@@ -30,9 +30,12 @@ export const createMockJobExecution = (partialRecord: Partial<JobExecution> = {}
30
30
  timeFinished: null,
31
31
  timeQueued,
32
32
  timeStarted: null,
33
- type: `${PARTITION_KEYS.jobExecution}-${jobName}`,
33
+ type: `${ENTITY_TYPES.jobExecution}-${jobName}`,
34
34
  version,
35
35
  input,
36
+ retryCount: 0,
37
+ lastFailureReason: null,
38
+ retryAfter: null,
36
39
  ...partialRecord,
37
40
  };
38
41
  };