teraslice 3.3.0 → 3.3.2

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 (108) hide show
  1. package/LICENSE +202 -0
  2. package/package.json +25 -28
  3. package/dist/src/interfaces.js +0 -12
  4. package/dist/src/lib/cluster/cluster_master.js +0 -246
  5. package/dist/src/lib/cluster/node_master.js +0 -355
  6. package/dist/src/lib/cluster/services/api.js +0 -663
  7. package/dist/src/lib/cluster/services/assets.js +0 -224
  8. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/index.js +0 -192
  9. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/interfaces.js +0 -2
  10. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8s.js +0 -419
  11. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sDeploymentResource.js +0 -60
  12. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sJobResource.js +0 -55
  13. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sResource.js +0 -357
  14. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sServiceResource.js +0 -37
  15. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sState.js +0 -60
  16. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/utils.js +0 -170
  17. package/dist/src/lib/cluster/services/cluster/backends/native/dispatch.js +0 -13
  18. package/dist/src/lib/cluster/services/cluster/backends/native/index.js +0 -526
  19. package/dist/src/lib/cluster/services/cluster/backends/native/messaging.js +0 -548
  20. package/dist/src/lib/cluster/services/cluster/backends/state-utils.js +0 -26
  21. package/dist/src/lib/cluster/services/cluster/index.js +0 -13
  22. package/dist/src/lib/cluster/services/execution.js +0 -435
  23. package/dist/src/lib/cluster/services/index.js +0 -6
  24. package/dist/src/lib/cluster/services/interfaces.js +0 -2
  25. package/dist/src/lib/cluster/services/jobs.js +0 -458
  26. package/dist/src/lib/config/default-sysconfig.js +0 -25
  27. package/dist/src/lib/config/index.js +0 -20
  28. package/dist/src/lib/config/schemas/system.js +0 -360
  29. package/dist/src/lib/storage/analytics.js +0 -86
  30. package/dist/src/lib/storage/assets.js +0 -401
  31. package/dist/src/lib/storage/backends/elasticsearch_store.js +0 -496
  32. package/dist/src/lib/storage/backends/mappings/analytics.js +0 -20
  33. package/dist/src/lib/storage/backends/mappings/asset.js +0 -32
  34. package/dist/src/lib/storage/backends/mappings/ex.js +0 -53
  35. package/dist/src/lib/storage/backends/mappings/job.js +0 -42
  36. package/dist/src/lib/storage/backends/mappings/state.js +0 -16
  37. package/dist/src/lib/storage/backends/s3_store.js +0 -237
  38. package/dist/src/lib/storage/execution.js +0 -302
  39. package/dist/src/lib/storage/index.js +0 -7
  40. package/dist/src/lib/storage/jobs.js +0 -81
  41. package/dist/src/lib/storage/state.js +0 -254
  42. package/dist/src/lib/utils/api_utils.js +0 -128
  43. package/dist/src/lib/utils/asset_utils.js +0 -94
  44. package/dist/src/lib/utils/date_utils.js +0 -52
  45. package/dist/src/lib/utils/encoding_utils.js +0 -27
  46. package/dist/src/lib/utils/events.js +0 -4
  47. package/dist/src/lib/utils/file_utils.js +0 -124
  48. package/dist/src/lib/utils/id_utils.js +0 -15
  49. package/dist/src/lib/utils/port_utils.js +0 -32
  50. package/dist/src/lib/workers/assets/index.js +0 -3
  51. package/dist/src/lib/workers/assets/loader-executable.js +0 -40
  52. package/dist/src/lib/workers/assets/loader.js +0 -73
  53. package/dist/src/lib/workers/assets/spawn.js +0 -55
  54. package/dist/src/lib/workers/context/execution-context.js +0 -12
  55. package/dist/src/lib/workers/context/terafoundation-context.js +0 -8
  56. package/dist/src/lib/workers/execution-controller/execution-analytics.js +0 -188
  57. package/dist/src/lib/workers/execution-controller/index.js +0 -1024
  58. package/dist/src/lib/workers/execution-controller/recovery.js +0 -151
  59. package/dist/src/lib/workers/execution-controller/scheduler.js +0 -390
  60. package/dist/src/lib/workers/execution-controller/slice-analytics.js +0 -96
  61. package/dist/src/lib/workers/helpers/job.js +0 -80
  62. package/dist/src/lib/workers/helpers/op-analytics.js +0 -22
  63. package/dist/src/lib/workers/helpers/terafoundation.js +0 -34
  64. package/dist/src/lib/workers/helpers/worker-shutdown.js +0 -147
  65. package/dist/src/lib/workers/metrics/index.js +0 -108
  66. package/dist/src/lib/workers/worker/index.js +0 -378
  67. package/dist/src/lib/workers/worker/slice.js +0 -122
  68. package/dist/test/config/schemas/system_schema-spec.js +0 -26
  69. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8s-v2-spec.js +0 -458
  70. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sResource-v2-spec.js +0 -818
  71. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sState-multicluster-v2-spec.js +0 -67
  72. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sState-v2-spec.js +0 -84
  73. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/utils-v2-spec.js +0 -320
  74. package/dist/test/lib/cluster/services/cluster/backends/state-utils-spec.js +0 -37
  75. package/dist/test/node_master-spec.js +0 -194
  76. package/dist/test/services/api-spec.js +0 -79
  77. package/dist/test/services/assets-spec.js +0 -158
  78. package/dist/test/services/messaging-spec.js +0 -440
  79. package/dist/test/storage/assets_storage-spec.js +0 -95
  80. package/dist/test/storage/s3_store-spec.js +0 -149
  81. package/dist/test/test.config.js +0 -23
  82. package/dist/test/test.setup.js +0 -6
  83. package/dist/test/utils/api_utils-spec.js +0 -25
  84. package/dist/test/utils/asset_utils-spec.js +0 -141
  85. package/dist/test/utils/elastic_utils-spec.js +0 -25
  86. package/dist/test/workers/execution-controller/execution-controller-spec.js +0 -371
  87. package/dist/test/workers/execution-controller/execution-special-test-cases-spec.js +0 -519
  88. package/dist/test/workers/execution-controller/execution-test-cases-spec.js +0 -343
  89. package/dist/test/workers/execution-controller/recovery-spec.js +0 -160
  90. package/dist/test/workers/execution-controller/scheduler-spec.js +0 -249
  91. package/dist/test/workers/execution-controller/slice-analytics-spec.js +0 -121
  92. package/dist/test/workers/fixtures/ops/example-op/processor.js +0 -20
  93. package/dist/test/workers/fixtures/ops/example-op/schema.js +0 -19
  94. package/dist/test/workers/fixtures/ops/example-reader/fetcher.js +0 -20
  95. package/dist/test/workers/fixtures/ops/example-reader/schema.js +0 -41
  96. package/dist/test/workers/fixtures/ops/example-reader/slicer.js +0 -37
  97. package/dist/test/workers/fixtures/ops/new-op/processor.js +0 -29
  98. package/dist/test/workers/fixtures/ops/new-op/schema.js +0 -18
  99. package/dist/test/workers/fixtures/ops/new-reader/fetcher.js +0 -19
  100. package/dist/test/workers/fixtures/ops/new-reader/schema.js +0 -23
  101. package/dist/test/workers/fixtures/ops/new-reader/slicer.js +0 -13
  102. package/dist/test/workers/helpers/configs.js +0 -128
  103. package/dist/test/workers/helpers/execution-controller-helper.js +0 -49
  104. package/dist/test/workers/helpers/index.js +0 -5
  105. package/dist/test/workers/helpers/test-context.js +0 -210
  106. package/dist/test/workers/helpers/zip-directory.js +0 -25
  107. package/dist/test/workers/worker/slice-spec.js +0 -333
  108. package/dist/test/workers/worker/worker-spec.js +0 -356
@@ -1,237 +0,0 @@
1
- import { TSError, isTest, logError, pDelay, pWhile, random } from '@terascope/core-utils';
2
- import { S3ClientResponse, createS3Bucket, deleteS3Object, doesBucketExist, getS3Object, listS3Objects, putS3Object, s3RequestWithRetry } from '@terascope/file-asset-apis';
3
- import { makeLogger } from '../../workers/helpers/terafoundation.js';
4
- export class S3Store {
5
- bucket;
6
- connection;
7
- terafoundation;
8
- isShuttingDown;
9
- logger;
10
- api;
11
- context;
12
- constructor(backendConfig) {
13
- const { context, terafoundation, connection, bucket, logger } = backendConfig;
14
- this.context = context;
15
- this.bucket = bucket || this.createDefaultBucketName();
16
- this.connection = connection;
17
- this.isShuttingDown = false;
18
- this.logger = logger ?? makeLogger(context, 's3_backend', { storageName: this.bucket });
19
- this.terafoundation = terafoundation;
20
- }
21
- async initialize() {
22
- const { client } = await this.context.apis.foundation
23
- .createClient({ type: 's3', cached: true, endpoint: this.connection });
24
- this.api = client;
25
- await pWhile(async () => {
26
- try {
27
- const exists = await doesBucketExist(client, { Bucket: this.bucket });
28
- if (!exists) {
29
- await createS3Bucket(client, { Bucket: this.bucket });
30
- }
31
- const isReady = await this.verifyClient();
32
- return isReady;
33
- }
34
- catch (err) {
35
- if (err.Code === 'InvalidAccessKeyId') {
36
- throw new TSError(`accessKeyId ${this.terafoundation.connectors.s3[this.connection].accessKeyId} specified in S3 ${this.connection} does not exit: ${err.message}`);
37
- }
38
- if (err.Code === 'SignatureDoesNotMatch') {
39
- throw new TSError(`secretAccessKey specified in S3 ${this.connection} does not match accessKeyId: ${err.message}`);
40
- }
41
- if (err.Code === 'InvalidBucketName') {
42
- throw new TSError(`Bucket name does not follow S3 naming rules: ${err.message}`);
43
- }
44
- if (err instanceof S3ClientResponse.BucketAlreadyExists) {
45
- throw new TSError(`Bucket name ${this.bucket} not available. accessKeyId ${this.terafoundation.connectors.s3[this.connection].accessKeyId} does not own this bucket. ${err.message}`);
46
- }
47
- logError(this.logger, err, `Failed attempt connecting to S3 ${this.connection} connection, ${this.bucket} bucket (will retry)`);
48
- await pDelay(isTest ? 0 : random(2000, 4000));
49
- return false;
50
- }
51
- });
52
- }
53
- // TODO: if we want to use the S3 store more generically we can't
54
- // assume the key will have a '.zip' extension
55
- async get(recordId) {
56
- const command = {
57
- Bucket: this.bucket,
58
- Key: `${recordId}.zip`
59
- };
60
- try {
61
- this.logger.debug(`getting record with id: ${recordId} from s3 ${this.connection} connection, ${this.bucket} bucket.`);
62
- const client = this.api;
63
- const bufferArray = [];
64
- let triggerReturn = false;
65
- const response = await s3RequestWithRetry({
66
- client,
67
- func: getS3Object,
68
- params: command
69
- });
70
- /// Convert the response body to a Node read stream
71
- const s3Stream = response.Body;
72
- /// Store the data coming into s3 into a buffer array
73
- s3Stream.on('data', (chunk) => {
74
- bufferArray.push(chunk);
75
- });
76
- s3Stream.on('end', () => {
77
- triggerReturn = true;
78
- });
79
- s3Stream.on('error', (err) => {
80
- throw new TSError(`Unable to get recordId ${recordId} from s3 ${this.connection} connection, ${this.bucket} bucket.
81
- Reason: ${err.message}`);
82
- });
83
- await pWhile(async () => triggerReturn);
84
- return Buffer.concat(bufferArray);
85
- }
86
- catch (err) {
87
- if (err instanceof S3ClientResponse.NoSuchKey) {
88
- throw new TSError(`recordId ${recordId} does not exist in s3 ${this.connection} connection, ${this.bucket} bucket.`, {
89
- statusCode: 404
90
- });
91
- }
92
- throw new TSError(`Retrieval of recordId ${recordId} from s3 ${this.connection} connection, ${this.bucket} bucket failed: `, err);
93
- }
94
- }
95
- async save(recordId, data, timeout) {
96
- try {
97
- this.logger.debug(`saving recordId ${recordId} to s3 ${this.connection} connection, ${this.bucket} bucket.`);
98
- const command = {
99
- Bucket: this.bucket,
100
- Key: `${recordId}.zip`,
101
- Body: data
102
- };
103
- const timeoutID = setTimeout(() => {
104
- throw new TSError(`Timeout saving recordId ${recordId}`);
105
- }, timeout);
106
- try {
107
- const client = this.api;
108
- await s3RequestWithRetry({
109
- client,
110
- func: putS3Object,
111
- params: command
112
- });
113
- }
114
- catch (err) {
115
- throw new TSError(`Failure saving recordId ${recordId} to S3: ${err}`);
116
- }
117
- finally {
118
- clearTimeout(timeoutID);
119
- }
120
- }
121
- catch (err) {
122
- throw new TSError(`Error saving recordId ${recordId} to S3 ${this.connection} connection, ${this.bucket} bucket: ${err}`);
123
- }
124
- }
125
- async remove(recordId) {
126
- try {
127
- this.logger.debug(`removing record ${recordId} from s3 ${this.connection} connection, ${this.bucket} bucket.`);
128
- const command = {
129
- Bucket: this.bucket,
130
- Key: `${recordId}.zip`
131
- };
132
- const client = this.api;
133
- await s3RequestWithRetry({
134
- client,
135
- func: deleteS3Object,
136
- params: command
137
- });
138
- }
139
- catch (err) {
140
- throw new TSError(`Error deleting recordId ${recordId} from s3 ${this.connection} connection, ${this.bucket} bucket: ${err}`);
141
- }
142
- }
143
- async list() {
144
- /// list all keys in bucket
145
- const objectList = [];
146
- let nextContinuationToken;
147
- let continuePagination = true;
148
- try {
149
- do {
150
- const command = {
151
- Bucket: this.bucket,
152
- ContinuationToken: nextContinuationToken || undefined,
153
- // MaxKeys: 1000 // Default is 1000
154
- };
155
- const client = this.api;
156
- const response = await s3RequestWithRetry({
157
- client,
158
- func: listS3Objects,
159
- params: command
160
- });
161
- response.Contents?.forEach((c) => {
162
- const s3Record = {
163
- File: c.Key,
164
- Size: c.Size,
165
- // Created: c.LastModified
166
- };
167
- objectList.push(s3Record);
168
- });
169
- if (!response.IsTruncated) {
170
- continuePagination = false;
171
- nextContinuationToken = undefined;
172
- }
173
- else {
174
- nextContinuationToken = response.NextContinuationToken;
175
- }
176
- const recordsReceived = response.Contents?.length || 0;
177
- this.logger.debug(`Received ${recordsReceived} records from s3 ${this.connection} connection, ${this.bucket} bucket.`);
178
- } while (continuePagination);
179
- this.logger.info(`Found ${objectList.length} records in s3 ${this.connection} connection, ${this.bucket} bucket.`);
180
- }
181
- catch (err) {
182
- throw new TSError(`Error listing records from s3 ${this.connection} connection, ${this.bucket} bucket: ${err}`);
183
- }
184
- return objectList;
185
- }
186
- /*
187
- * The S3 client has no built in functionality to determine if the client is connected.
188
- * If we can make a request to ListS3Objects then we know that the bucket exists and
189
- * credentials are valid.
190
- */
191
- async verifyClient() {
192
- if (this.isShuttingDown)
193
- return false;
194
- const command = {
195
- Bucket: this.bucket
196
- };
197
- const config = this.terafoundation.connectors.s3[this.connection];
198
- try {
199
- const client = this.api;
200
- await s3RequestWithRetry({
201
- client,
202
- func: listS3Objects,
203
- params: command
204
- });
205
- this.logger.debug(`S3 Client verification succeeded. Connection: ${this.connection}, endpoint: ${config.endpoint}`);
206
- return true;
207
- }
208
- catch (err) {
209
- this.logger.debug(`S3 Client verification failed. Connection: ${this.connection}, endpoint: ${config.endpoint}: `, err);
210
- return false;
211
- }
212
- }
213
- async waitForClient() {
214
- this.logger.debug('waiting for s3 client');
215
- if (await this.verifyClient())
216
- return;
217
- await pWhile(async () => {
218
- if (this.isShuttingDown)
219
- throw new Error('S3 store is shutdown');
220
- if (await this.verifyClient())
221
- return true;
222
- await pDelay(100);
223
- return false;
224
- });
225
- }
226
- async shutdown() {
227
- this.isShuttingDown = true;
228
- this.api.destroy();
229
- }
230
- // TODO: Use more generic bucket prefix (not related to assets)
231
- // or pass in prefix from calling class
232
- createDefaultBucketName() {
233
- const safeName = this.context.sysconfig.teraslice.name.replaceAll('_', '-');
234
- return `ts-assets-${safeName}`;
235
- }
236
- }
237
- //# sourceMappingURL=s3_store.js.map
@@ -1,302 +0,0 @@
1
- import { TSError, includes, getTypeOf, makeISODate } from '@terascope/core-utils';
2
- import { RecoveryCleanupType } from '@terascope/job-components';
3
- import { v4 as uuid } from 'uuid';
4
- import { makeLogger } from '../workers/helpers/terafoundation.js';
5
- import { TerasliceElasticsearchStorage } from './backends/elasticsearch_store.js';
6
- import { getPackageJSON } from '../utils/file_utils.js';
7
- const INIT_STATUS = ['pending', 'scheduling', 'initializing'];
8
- const RUNNING_STATUS = ['recovering', 'running', 'failing', 'paused', 'stopping'];
9
- const TERMINAL_STATUS = ['completed', 'stopped', 'rejected', 'failed', 'terminated'];
10
- const VALID_STATUS = INIT_STATUS.concat(RUNNING_STATUS).concat(TERMINAL_STATUS);
11
- // Module to manager job states in Elasticsearch.
12
- // All functions in this module return promises that must be resolved to
13
- // get the final result.
14
- export class ExecutionStorage {
15
- backend;
16
- jobType;
17
- logger;
18
- constructor(context) {
19
- const logger = makeLogger(context, 'ex_storage');
20
- const config = context.sysconfig.teraslice;
21
- const jobType = 'ex';
22
- const indexName = `${config.name}__ex`;
23
- const backendConfig = {
24
- context,
25
- indexName,
26
- recordType: 'ex',
27
- idField: 'ex_id',
28
- fullResponse: false,
29
- logRecord: false,
30
- storageName: 'execution',
31
- logger
32
- };
33
- this.jobType = jobType;
34
- this.logger = logger;
35
- this.backend = new TerasliceElasticsearchStorage(backendConfig);
36
- if (context.apis.executionContext) {
37
- context.apis.executionContext.registerMetadataFns({ get: this.getMetadata.bind(this), update: this.updateMetadata.bind(this) });
38
- }
39
- }
40
- async initialize() {
41
- await this.backend.initialize();
42
- this.logger.info('execution storage initialized');
43
- }
44
- async get(exId) {
45
- const results = await this.backend.get(exId);
46
- return results;
47
- }
48
- // encompasses all executions in either initialization or running statuses
49
- async getActiveExecution(exId) {
50
- const str = this.getTerminalStatuses().map((state) => ` _status:${state} `)
51
- .join('OR');
52
- const query = `ex_id:"${exId}" NOT (${str.trim()})`;
53
- const executions = await this.backend.search(query, undefined, 1, '_created:desc');
54
- if (!executions.length) {
55
- throw new TSError(`no active execution context was found for ex_id: ${exId}`, {
56
- statusCode: 404
57
- });
58
- }
59
- return executions[0];
60
- }
61
- async search(query, from, size, sort, fields) {
62
- const results = await this.backend.search(query, from, size, sort, fields);
63
- return results;
64
- }
65
- async create(record, status = 'pending') {
66
- if (!this._isValidStatus(status)) {
67
- throw new Error(`Unknown status "${status}" on execution create`);
68
- }
69
- if (!record.job_id) {
70
- throw new Error('Missing job_id on execution create');
71
- }
72
- const date = makeISODate();
73
- const doc = Object.assign({}, record, {
74
- ex_id: uuid(),
75
- metadata: {},
76
- _status: status,
77
- _context: this.jobType,
78
- _created: date,
79
- _updated: date,
80
- _has_errors: false,
81
- _slicer_stats: {},
82
- _failureReason: '',
83
- teraslice_version: `v${getPackageJSON().version}`
84
- });
85
- // @ts-expect-error
86
- delete doc.slicer_port;
87
- // @ts-expect-error
88
- delete doc.slicer_hostname;
89
- try {
90
- await this.backend.create(doc);
91
- }
92
- catch (err) {
93
- throw new TSError(err, {
94
- reason: 'Failure to create execution context'
95
- });
96
- }
97
- return doc;
98
- }
99
- async updatePartial(exId, applyChanges) {
100
- return this.backend.updatePartial(exId, applyChanges);
101
- }
102
- /**
103
- * @typedef ExErrorMetadata
104
- * @property _has_errors {boolean}
105
- * @property _failureReason {string}
106
- * @property _slicer_stats {import(
107
- * '../workers/execution-controller/execution-analytics.js'
108
- * ).ExecutionStats}
109
- */
110
- /**
111
- * Format the execution error stats, primarly used for updating the
112
- * status.
113
- *
114
- * If no error message is passed, it will reset the _has_errors and _failureReason.
115
- * If execution stats is provided it will set the _slicer_stats
116
- *
117
- * @param stats {import(
118
- * '../workers/execution-controller/execution-analytics.js'
119
- * ).ExecutionStats=}
120
- * @param errMsg {string=}
121
- * @return {ExErrorMetadata}
122
- */
123
- // TODO: type out stats
124
- executionMetaData(stats, errMsg) {
125
- const errMetadata = {
126
- _has_errors: false,
127
- _failureReason: ''
128
- };
129
- const statsMetadata = {};
130
- if (errMsg) {
131
- errMetadata._has_errors = true;
132
- errMetadata._failureReason = errMsg;
133
- }
134
- if (stats) {
135
- statsMetadata._slicer_stats = Object.assign({}, stats);
136
- }
137
- return Object.assign({}, errMetadata, statsMetadata);
138
- }
139
- async getMetadata(exId) {
140
- const ex = await this.get(exId);
141
- return ex.metadata ?? {};
142
- }
143
- // TODO: type this
144
- async updateMetadata(exId, metadata = {}) {
145
- await this.backend.update(exId, {
146
- metadata,
147
- _updated: makeISODate()
148
- });
149
- }
150
- // TODO: put a type of return
151
- async getStatus(exId) {
152
- try {
153
- const result = await this.get(exId);
154
- return result._status;
155
- }
156
- catch (err) {
157
- throw new TSError(err, {
158
- reason: `Cannot get execution status ${exId}`
159
- });
160
- }
161
- }
162
- // TODO: type this
163
- // verify the current status to make sure it can be updated to the desired status
164
- async verifyStatusUpdate(exId, desiredStatus) {
165
- if (!desiredStatus || !this._isValidStatus(desiredStatus)) {
166
- throw new TSError(`Invalid Job status: "${desiredStatus}"`, {
167
- statusCode: 422
168
- });
169
- }
170
- const status = await this.getStatus(exId);
171
- this._verifyStatus(status, desiredStatus);
172
- }
173
- _verifyStatus(status, desiredStatus) {
174
- // when setting the same status to shouldn't throw an error
175
- if (desiredStatus === status) {
176
- return status;
177
- }
178
- // when the current status is running it cannot be set to an init status
179
- if (this._isRunningStatus(status) && this._isInitStatus(desiredStatus)) {
180
- throw new TSError(`Cannot update running job status of "${status}" to init status of "${desiredStatus}"`, {
181
- statusCode: 422
182
- });
183
- }
184
- // if it is set to stop but the execution finishes before it can stop
185
- // it is okay to set it to completed
186
- if (status === 'stopped' && desiredStatus === 'completed') {
187
- return status;
188
- }
189
- // when the status is a terminal status, it cannot be set to again
190
- if (this._isTerminalStatus(status)) {
191
- throw new TSError(`Cannot update terminal job status of "${status}" to "${desiredStatus}"`, {
192
- statusCode: 422
193
- });
194
- }
195
- // otherwise allow the update
196
- return status;
197
- }
198
- // TODO: type this
199
- /**
200
- * Set the status
201
- *
202
- * @param {string} exId
203
- * @param {string} status
204
- * @param {Partial<import('@terascope/job-components').ExecutionConfig>} body
205
- * @returns {Promise<import('@terascope/job-components').ExecutionConfig>}
206
- */
207
- async setStatus(exId, status, body) {
208
- try {
209
- return await this.updatePartial(exId, async (existing) => {
210
- this._verifyStatus(existing._status, status);
211
- return Object.assign(existing, body, {
212
- _status: status,
213
- _updated: makeISODate()
214
- });
215
- });
216
- }
217
- catch (err) {
218
- throw new TSError(err, {
219
- statusCode: 422,
220
- reason: `Unable to set execution ${exId} status code to ${status}`
221
- });
222
- }
223
- }
224
- async softDelete(exId) {
225
- try {
226
- const date = makeISODate();
227
- return await this.updatePartial(exId, async (existing) => Object.assign(existing, {
228
- _deleted: true,
229
- _deleted_on: date,
230
- _updated: date
231
- }));
232
- }
233
- catch (err) {
234
- throw new TSError(err, {
235
- statusCode: 422,
236
- reason: `Unable to delete execution ${exId}`
237
- });
238
- }
239
- }
240
- async remove(exId) {
241
- return this.backend.remove(exId);
242
- }
243
- async shutdown(forceShutdown) {
244
- this.logger.info('shutting down.');
245
- return this.backend.shutdown(forceShutdown);
246
- }
247
- verifyClient() {
248
- return this.backend.verifyClient();
249
- }
250
- async waitForClient() {
251
- return this.backend.waitForClient();
252
- }
253
- getTerminalStatuses() {
254
- return TERMINAL_STATUS.slice();
255
- }
256
- getRunningStatuses() {
257
- return RUNNING_STATUS.slice();
258
- }
259
- getLivingStatuses() {
260
- return INIT_STATUS.concat(RUNNING_STATUS);
261
- }
262
- _isValidStatus(status) {
263
- return includes(VALID_STATUS, status);
264
- }
265
- _isRunningStatus(status) {
266
- return includes(RUNNING_STATUS, status);
267
- }
268
- _isTerminalStatus(status) {
269
- return includes(TERMINAL_STATUS, status);
270
- }
271
- _isInitStatus(status) {
272
- return includes(INIT_STATUS, status);
273
- }
274
- // TODO: fix types
275
- /**
276
- * @param {import('@terascope/job-components').ExecutionConfig} recoverFrom
277
- * @param {RecoveryCleanupType} [cleanupType]
278
- * @returns {Promise<import('@terascope/job-components').ExecutionConfig>}
279
- */
280
- async createRecoveredExecution(recoverFrom, cleanupType) {
281
- if (!recoverFrom) {
282
- throw new Error(`Invalid execution given, got ${getTypeOf(recoverFrom)}`);
283
- }
284
- if (!recoverFrom.ex_id) {
285
- throw new Error('Unable to recover execution with missing ex_id');
286
- }
287
- const recoverFromId = recoverFrom.ex_id;
288
- const ex = Object.assign({}, recoverFrom);
289
- if (cleanupType && !RecoveryCleanupType[cleanupType]) {
290
- throw new Error(`Unknown cleanup type "${cleanupType}" to recover`);
291
- }
292
- ex.recovered_execution = recoverFromId;
293
- if (cleanupType) {
294
- ex.recovered_slice_type = cleanupType;
295
- }
296
- else if (ex.autorecover) {
297
- ex.recovered_slice_type = RecoveryCleanupType.pending;
298
- }
299
- return this.create(ex);
300
- }
301
- }
302
- //# sourceMappingURL=execution.js.map
@@ -1,7 +0,0 @@
1
- import { AnalyticsStorage } from './analytics.js';
2
- import { AssetsStorage } from './assets.js';
3
- import { ExecutionStorage } from './execution.js';
4
- import { JobsStorage } from './jobs.js';
5
- import { StateStorage, SliceState } from './state.js';
6
- export { SliceState, AnalyticsStorage, AssetsStorage, ExecutionStorage, JobsStorage, StateStorage, };
7
- //# sourceMappingURL=index.js.map
@@ -1,81 +0,0 @@
1
- import { v4 as uuid } from 'uuid';
2
- import { TSError, makeISODate } from '@terascope/core-utils';
3
- import { makeLogger } from '../workers/helpers/terafoundation.js';
4
- import { TerasliceElasticsearchStorage } from './backends/elasticsearch_store.js';
5
- export class JobsStorage {
6
- backend;
7
- jobType;
8
- logger;
9
- constructor(context) {
10
- const logger = makeLogger(context, 'job_storage');
11
- const config = context.sysconfig.teraslice;
12
- const jobType = 'job';
13
- const indexName = `${config.name}__jobs`;
14
- const backendConfig = {
15
- context,
16
- indexName,
17
- recordType: 'job',
18
- idField: 'job_id',
19
- fullResponse: false,
20
- logRecord: false,
21
- storageName: 'jobs',
22
- logger
23
- };
24
- this.logger = logger;
25
- this.jobType = jobType;
26
- this.backend = new TerasliceElasticsearchStorage(backendConfig);
27
- }
28
- async initialize() {
29
- await this.backend.initialize();
30
- this.logger.info('job storage initialized');
31
- }
32
- async get(jobId) {
33
- const doc = await this.backend.get(jobId);
34
- return doc;
35
- }
36
- async search(query, from, size, sort, fields) {
37
- const results = await this.backend.search(query, from, size, sort, fields);
38
- return results;
39
- }
40
- async create(record) {
41
- const date = makeISODate();
42
- const doc = Object.assign({}, record, {
43
- job_id: uuid(),
44
- _context: this.jobType,
45
- _created: date,
46
- _updated: date
47
- });
48
- try {
49
- await this.backend.create(doc);
50
- }
51
- catch (err) {
52
- throw new TSError(err, {
53
- reason: 'Failure to create job'
54
- });
55
- }
56
- return doc;
57
- }
58
- async update(jobId, updateSpec) {
59
- // We want to save the whole job as it is posted, update api does partial doc updates
60
- const results = await this.backend.indexWithId(jobId, Object.assign({}, updateSpec, {
61
- job_id: jobId,
62
- _context: this.jobType,
63
- _updated: makeISODate()
64
- }));
65
- return results;
66
- }
67
- async remove(jobId) {
68
- return this.backend.remove(jobId);
69
- }
70
- async shutdown(forceShutdown) {
71
- this.logger.info('shutting down.');
72
- return this.backend.shutdown(forceShutdown);
73
- }
74
- verifyClient() {
75
- return this.backend.verifyClient();
76
- }
77
- async waitForClient() {
78
- return this.backend.waitForClient();
79
- }
80
- }
81
- //# sourceMappingURL=jobs.js.map