teraslice-client-js 2.12.2 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "teraslice-client-js",
3
3
  "displayName": "Teraslice Client (JavaScript)",
4
- "version": "2.12.2",
4
+ "version": "2.14.0",
5
5
  "description": "A Node.js client for teraslice jobs, assets, and cluster references.",
6
6
  "keywords": [
7
7
  "elasticsearch",
@@ -26,13 +26,13 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "auto-bind": "~5.0.1",
29
- "got": "~15.0.6",
30
- "@terascope/core-utils": "~2.12.1",
31
- "@terascope/types": "~2.12.0"
29
+ "got": "~15.1.0",
30
+ "@terascope/core-utils": "~2.14.0",
31
+ "@terascope/types": "~2.13.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "jest-extended": "~7.0.0",
35
- "nock": "~14.0.15"
35
+ "nock": "~14.0.16"
36
36
  },
37
37
  "engines": {
38
38
  "node": ">=22.0.0",
package/src/job.ts CHANGED
@@ -87,13 +87,13 @@ export default class Job extends Client {
87
87
  return this.post(`/jobs/${this._jobId}/_recover`, null, options);
88
88
  }
89
89
 
90
- async update(jobSpec: Teraslice.JobConfig): Promise<Teraslice.JobConfig> {
90
+ async update(jobSpec: Teraslice.JobConfig): Promise<Teraslice.ApiJobUpdateResponse> {
91
91
  return this.put(`/jobs/${this._jobId}`, jobSpec);
92
92
  }
93
93
 
94
94
  async updatePartial(
95
95
  jobSpec: Partial<Teraslice.JobConfig>
96
- ): Promise<Teraslice.JobConfig> {
96
+ ): Promise<Teraslice.ApiJobUpdateResponse> {
97
97
  const current = await this.config();
98
98
  const body: Teraslice.JobConfig = Object.assign({}, current, jobSpec);
99
99
  return this.update(body);
package/src/jobs.ts CHANGED
@@ -25,6 +25,30 @@ export default class Jobs extends Client {
25
25
  return this.wrap(job.job_id);
26
26
  }
27
27
 
28
+ // TODO: Teraslice v4 this exists to avoid a breaking change to submit() which returns just
29
+ // the Job. This is only used by teraslice-cli. In Teraslice v4, submit() should
30
+ // be updated to return warnings and this method removed.
31
+ // See https://github.com/terascope/teraslice/issues/4501
32
+ async submitWithWarnings(
33
+ jobSpec: Teraslice.JobConfigParams,
34
+ shouldNotStart?: boolean
35
+ ): Promise<{ job: Job; warnings: Teraslice.JobWarning[] }> {
36
+ if (!jobSpec) {
37
+ throw new TSError('Submit requires a jobSpec', {
38
+ statusCode: 400
39
+ });
40
+ }
41
+
42
+ const response: Teraslice.ApiJobCreateResponse = await this.post('/jobs', jobSpec, {
43
+ searchParams: { start: !shouldNotStart }
44
+ });
45
+
46
+ return {
47
+ job: this.wrap(response.job_id),
48
+ warnings: response.warnings ?? []
49
+ };
50
+ }
51
+
28
52
  async list(
29
53
  query?: Teraslice.JobSearchParams,
30
54
  searchOptions: RequestOptions = {}
package/test/job-spec.ts CHANGED
@@ -223,6 +223,41 @@ describe('Teraslice Job', () => {
223
223
  });
224
224
  });
225
225
 
226
+ describe('->start', () => {
227
+ describe('when the server returns deprecation warnings', () => {
228
+ const deprecationWarning: Teraslice.JobWarning = {
229
+ type: 'JobValidation',
230
+ reason: {
231
+ type: 'assetOperation',
232
+ kind: 'deprecation',
233
+ reason: {
234
+ _op: 'some-op',
235
+ field: 'old_field',
236
+ description: 'old_field is deprecated, use new_field instead',
237
+ },
238
+ },
239
+ };
240
+
241
+ const response: Teraslice.ApiJobCreateResponse = {
242
+ job_id: 'some-job-id',
243
+ warnings: [deprecationWarning],
244
+ };
245
+
246
+ beforeEach(() => {
247
+ scope.post('/jobs/some-job-id/_start')
248
+ .reply(200, response);
249
+ });
250
+
251
+ it('should return the response with warnings', async () => {
252
+ const job = new Job({ baseUrl }, 'some-job-id');
253
+ const result = await job.start();
254
+ expect(result.job_id).toEqual('some-job-id');
255
+ expect(result.warnings).toBeArrayOfSize(1);
256
+ expect(result.warnings![0]).toMatchObject(deprecationWarning);
257
+ });
258
+ });
259
+ });
260
+
226
261
  describe('->recover', () => {
227
262
  describe('when called with nothing', () => {
228
263
  beforeEach(() => {
@@ -275,6 +310,41 @@ describe('Teraslice Job', () => {
275
310
  });
276
311
  });
277
312
 
313
+ describe('->recover with warnings', () => {
314
+ describe('when the server returns deprecation warnings', () => {
315
+ const deprecationWarning: Teraslice.JobWarning = {
316
+ type: 'JobValidation',
317
+ reason: {
318
+ type: 'assetAPIProperty',
319
+ kind: 'deprecation',
320
+ reason: {
321
+ api_name: 'some-api',
322
+ field: 'old_api_field',
323
+ description: 'old_api_field is deprecated, use new_api_field instead',
324
+ },
325
+ },
326
+ };
327
+
328
+ const response: Teraslice.ApiJobCreateResponse = {
329
+ job_id: 'some-other-job-id',
330
+ warnings: [deprecationWarning],
331
+ };
332
+
333
+ beforeEach(() => {
334
+ scope.post('/jobs/some-other-job-id/_recover')
335
+ .reply(200, response);
336
+ });
337
+
338
+ it('should return the response with warnings', async () => {
339
+ const job = new Job({ baseUrl }, 'some-other-job-id');
340
+ const result = await job.recover();
341
+ expect(result.job_id).toEqual('some-other-job-id');
342
+ expect(result.warnings).toBeArrayOfSize(1);
343
+ expect(result.warnings![0]).toMatchObject(deprecationWarning);
344
+ });
345
+ });
346
+ });
347
+
278
348
  describe('->execution', () => {
279
349
  const exJobId = executionResults[0].job_id;
280
350
  describe('when called with nothing', () => {
package/test/jobs-spec.ts CHANGED
@@ -164,6 +164,81 @@ describe('Teraslice Jobs', () => {
164
164
  });
165
165
  });
166
166
 
167
+ describe('->submitWithWarnings', () => {
168
+ describe('when submitting without a jobSpec', () => {
169
+ it('should fail', async () => {
170
+ expect.hasAssertions();
171
+ try {
172
+ // @ts-expect-error
173
+ await jobs.submitWithWarnings();
174
+ } catch (err) {
175
+ expect(err.message).toEqual('Submit requires a jobSpec');
176
+ }
177
+ });
178
+ });
179
+
180
+ describe('when the server returns warnings', () => {
181
+ const jobSpec = { operations: [{ _op: 'operation' }] };
182
+ const response = {
183
+ job_id: 'some-job-id',
184
+ warnings: [{
185
+ type: 'JobValidation',
186
+ reason: {
187
+ type: 'assetOperation',
188
+ kind: 'deprecation',
189
+ reason: {
190
+ _op: 'operation',
191
+ field: 'old_field',
192
+ description: 'old_field is deprecated',
193
+ },
194
+ },
195
+ }]
196
+ };
197
+
198
+ beforeEach(() => {
199
+ scope.post('/jobs', jobSpec)
200
+ .query({ start: false })
201
+ .reply(202, response);
202
+ });
203
+
204
+ it('should return the job and warnings', async () => {
205
+ const result = await jobs.submitWithWarnings(jobSpec, true);
206
+ expect(result.job).toBeInstanceOf(Job);
207
+ expect(result.job.id()).toEqual(response.job_id);
208
+ expect(result.warnings).toBeArrayOfSize(1);
209
+ expect(result.warnings[0]).toMatchObject({
210
+ type: 'JobValidation',
211
+ reason: {
212
+ type: 'assetOperation',
213
+ kind: 'deprecation',
214
+ reason: {
215
+ _op: 'operation',
216
+ field: 'old_field',
217
+ description: 'old_field is deprecated',
218
+ },
219
+ },
220
+ });
221
+ });
222
+ });
223
+
224
+ describe('when the response includes no warnings field', () => {
225
+ const jobSpec = { operations: [{ _op: 'operation' }] };
226
+ const response = { job_id: 'some-job-id' };
227
+
228
+ beforeEach(() => {
229
+ scope.post('/jobs', jobSpec)
230
+ .query({ start: false })
231
+ .reply(202, response);
232
+ });
233
+
234
+ it('should return the job with an empty warnings array', async () => {
235
+ const result = await jobs.submitWithWarnings(jobSpec, true);
236
+ expect(result.job).toBeInstanceOf(Job);
237
+ expect(result.warnings).toBeArrayOfSize(0);
238
+ });
239
+ });
240
+ });
241
+
167
242
  describe('->list', () => {
168
243
  describe('when called with nothing', () => {
169
244
  beforeEach(() => {