@natlibfi/melinda-rest-api-commons 2.2.0-alpha.2 → 2.2.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mongo.js CHANGED
@@ -50,6 +50,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
50
50
  * for the JavaScript code in this file.
51
51
  *
52
52
  */
53
+ //import isDeepStrictEqual from 'util';
53
54
 
54
55
  /* QueueItem:
55
56
  {
@@ -57,6 +58,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
57
58
  "cataloger":"xxx0000",
58
59
  "oCatalogerIn":"xxx0000"
59
60
  "operation":"UPDATE",
61
+ "operations":["UPDATE", "CREATE"]
60
62
  "contentType":"application/json",
61
63
  "recordLoadParams": {
62
64
  "pActiveLibrary": "XXX00",
@@ -66,9 +68,16 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
66
68
  "pOldNew": "NEW"
67
69
  },
68
70
  "queueItemState":"PENDING_QUEUING",
71
+ "importJobState": {
72
+ "CREATE": "EMPTY",
73
+ "UPDATE": "EMPTY"
74
+ },
75
+ blobSize: 1,
76
+ records: [],
77
+ errorMessage: '',
78
+ errorStatus: '',
69
79
  "creationTime":"2020-01-01T00:00:00.000Z",
70
80
  "modificationTime":"2020-01-01T00:00:01.000Z",
71
- "handledIds": []
72
81
  }
73
82
  */
74
83
  async function _default(MONGO_URI, collection) {
@@ -86,6 +95,7 @@ async function _default(MONGO_URI, collection) {
86
95
  createPrio,
87
96
  createBulk,
88
97
  checkAndSetState,
98
+ checkAndSetImportJobState,
89
99
  query,
90
100
  queryById,
91
101
  remove,
@@ -94,8 +104,13 @@ async function _default(MONGO_URI, collection) {
94
104
  getOne,
95
105
  getStream,
96
106
  setState,
107
+ setImportJobState,
97
108
  pushIds,
98
- pushMessages
109
+ pushMessages,
110
+ setOperation,
111
+ setOperations,
112
+ addBlobSize,
113
+ setBlobSize
99
114
  };
100
115
 
101
116
  async function createPrio({
@@ -103,26 +118,30 @@ async function _default(MONGO_URI, collection) {
103
118
  cataloger,
104
119
  oCatalogerIn,
105
120
  operation,
106
- noop = undefined,
107
- unique = undefined,
108
- prio = true
121
+ operationSettings
109
122
  }) {
110
123
  const time = (0, _moment.default)().toDate();
111
124
  const newQueueItem = {
112
125
  correlationId,
113
126
  cataloger,
114
127
  operation,
128
+ operations: [operation],
115
129
  oCatalogerIn,
116
130
  operationSettings: {
117
- unique,
118
- noop,
119
- prio
131
+ prio: true,
132
+ ...operationSettings
120
133
  },
121
134
  queueItemState: _constants.QUEUE_ITEM_STATE.VALIDATOR.PENDING_VALIDATION,
135
+ blobSize: 1,
136
+ importJobState: {
137
+ CREATE: _constants.IMPORT_JOB_STATE.EMPTY,
138
+ UPDATE: _constants.IMPORT_JOB_STATE.EMPTY
139
+ },
140
+ records: [],
141
+ errorMessage: '',
142
+ errorStatus: '',
122
143
  creationTime: time,
123
- modificationTime: time,
124
- handledIds: [],
125
- rejectedIds: []
144
+ modificationTime: time
126
145
  };
127
146
 
128
147
  try {
@@ -140,7 +159,7 @@ async function _default(MONGO_URI, collection) {
140
159
  }
141
160
  }
142
161
 
143
- function createBulk({
162
+ async function createBulk({
144
163
  correlationId,
145
164
  cataloger,
146
165
  oCatalogerIn,
@@ -148,7 +167,7 @@ async function _default(MONGO_URI, collection) {
148
167
  contentType,
149
168
  recordLoadParams,
150
169
  stream,
151
- prio = false
170
+ operationSettings
152
171
  }) {
153
172
  const time = (0, _moment.default)().toDate();
154
173
  const newQueueItem = {
@@ -156,40 +175,63 @@ async function _default(MONGO_URI, collection) {
156
175
  cataloger,
157
176
  oCatalogerIn,
158
177
  operation,
178
+ operations: [operation],
159
179
  operationSettings: {
160
- prio
180
+ prio: false,
181
+ ...operationSettings
161
182
  },
162
183
  contentType,
163
184
  recordLoadParams,
164
185
  queueItemState: stream ? _constants.QUEUE_ITEM_STATE.VALIDATOR.UPLOADING : _constants.QUEUE_ITEM_STATE.VALIDATOR.WAITING_FOR_RECORDS,
186
+ blobSize: 0,
187
+ importJobState: {
188
+ CREATE: _constants.IMPORT_JOB_STATE.EMPTY,
189
+ UPDATE: _constants.IMPORT_JOB_STATE.EMPTY
190
+ },
191
+ records: [],
192
+ errorMessage: '',
193
+ errorStatus: '',
165
194
  creationTime: time,
166
- modificationTime: time,
167
- handledIds: [],
168
- rejectedIds: []
169
- };
170
-
171
- try {
172
- // No await here, promises later
173
- db.collection(collection).insertOne(newQueueItem);
174
- logger.info(`New BULK queue item for ${operation} ${correlationId} has been made in ${collection}!`);
175
- } catch (error) {
176
- (0, _utils.logError)(error);
177
- throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR);
195
+ modificationTime: time
196
+ }; // eslint-disable-next-line functional/no-conditional-statement
197
+
198
+ if (stream) {
199
+ try {
200
+ // No await here, promises later
201
+ db.collection(collection).insertOne(newQueueItem);
202
+ logger.info(`New BULK queue item for ${operation} ${correlationId} has been made in ${collection}!`);
203
+ return new Promise((resolve, reject) => {
204
+ const outputStream = gridFSBucket.openUploadStream(correlationId);
205
+ stream.on('error', reject).on('data', chunk => outputStream.write(chunk)).on('end', () => outputStream.end(undefined, undefined, () => {
206
+ resolve(correlationId);
207
+ }));
208
+ });
209
+ } catch (error) {
210
+ (0, _utils.logError)(error);
211
+ throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR);
212
+ }
178
213
  }
179
214
 
215
+ logger.debug(`No stream`); // eslint-disable-next-line functional/no-conditional-statement
216
+
180
217
  if (!stream) {
181
- return {
182
- correlationId,
183
- queueItemState: _constants.QUEUE_ITEM_STATE.VALIDATOR.WAITING_FOR_RECORDS
184
- };
185
- }
218
+ try {
219
+ const result = await db.collection(collection).insertOne(newQueueItem);
220
+
221
+ if (result.acknowledged) {
222
+ logger.info(`New noStream BULK queue item for ${operation} ${correlationId} has been made in ${collection}`);
223
+ return {
224
+ correlationId,
225
+ queueItemState: _constants.QUEUE_ITEM_STATE.VALIDATOR.WAITING_FOR_RECORDS
226
+ };
227
+ }
186
228
 
187
- return new Promise((resolve, reject) => {
188
- const outputStream = gridFSBucket.openUploadStream(correlationId);
189
- stream.on('error', reject).on('data', chunk => outputStream.write(chunk)).on('end', () => outputStream.end(undefined, undefined, () => {
190
- resolve(correlationId);
191
- }));
192
- });
229
+ throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR);
230
+ } catch (error) {
231
+ (0, _utils.logError)(error);
232
+ throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR);
233
+ }
234
+ }
193
235
  } // Check state that the queueItem has not waited too long and set state
194
236
 
195
237
 
@@ -201,7 +243,9 @@ async function _default(MONGO_URI, collection) {
201
243
  }) {
202
244
  // checkTimeOut returns true, if queueItem is fresher than 1 minute and it's state is not ABORT/ERROR
203
245
  // otherwise it sets queueItem to state ABORT (408, 'Timeout')
204
- const timeOut = await checkTimeOut(correlationId);
246
+ const timeOut = await checkTimeOut({
247
+ correlationId
248
+ });
205
249
 
206
250
  if (timeOut) {
207
251
  return setState({
@@ -212,29 +256,81 @@ async function _default(MONGO_URI, collection) {
212
256
  });
213
257
  }
214
258
 
259
+ return false;
260
+ } // Check state that the queueItem has not waited too long and set state
261
+
262
+
263
+ async function checkAndSetImportJobState({
264
+ correlationId,
265
+ operation,
266
+ importJobState,
267
+ errorMessage = '',
268
+ errorStatus = ''
269
+ }) {
270
+ // checkTimeOut returns true, if queueItem is fresher than 1 minute and it's state is not ABORT/ERROR
271
+ // otherwise it sets queueItem to state ABORT (408, 'Timeout')
272
+ logger.debug(`${correlationId}, ${importJobState}, ${operation}`);
273
+ const timeOut = await checkTimeOut({
274
+ correlationId,
275
+ operation,
276
+ importJobState
277
+ });
278
+
279
+ if (timeOut) {
280
+ return setImportJobState({
281
+ correlationId,
282
+ operation,
283
+ importJobState,
284
+ errorMessage,
285
+ errorStatus
286
+ });
287
+ }
288
+
215
289
  return false;
216
290
  }
217
291
 
218
- async function query(params) {
219
- const result = await db.collection(collection).find(params, {
292
+ async function query(params, showParams = {}) {
293
+ const {
294
+ showOperations = 0,
295
+ showOperationSettings = 0,
296
+ showRecordLoadParams = 0,
297
+ showImportJobState = 0
298
+ } = showParams;
299
+ const {
300
+ limit = 1000,
301
+ skip = 0,
302
+ ...rest
303
+ } = params;
304
+ const result = await db.collection(collection).find(rest, {
220
305
  projection: {
221
- _id: 0
306
+ _id: 0,
307
+ operations: showOperations,
308
+ operationSettings: showOperationSettings,
309
+ recordLoadParams: showRecordLoadParams,
310
+ importJobState: showImportJobState
222
311
  }
223
- }).toArray();
312
+ }).limit(parseInt(limit, 10)).skip(parseInt(skip, 10)).toArray();
224
313
  logger.debug(`Query result: ${result.length > 0 ? 'Found!' : 'Not found!'}`);
225
314
  return result;
226
315
  }
227
316
 
228
- async function queryById(correlationId, checkModTime) {
317
+ async function queryById({
318
+ correlationId,
319
+ checkModTime = false
320
+ }) {
229
321
  const result = await db.collection(collection).findOne({
230
322
  correlationId
231
323
  });
232
324
 
233
325
  if (checkModTime) {
234
- const timeOut = await checkTimeOut(correlationId);
326
+ const timeOut = await checkTimeOut({
327
+ correlationId
328
+ });
235
329
 
236
330
  if (timeOut) {
237
- return queryById(correlationId);
331
+ return queryById({
332
+ correlationId
333
+ });
238
334
  }
239
335
 
240
336
  return result;
@@ -247,15 +343,18 @@ async function _default(MONGO_URI, collection) {
247
343
  // If the state is already ABORT or ERROR return false
248
344
 
249
345
 
250
- async function checkTimeOut(correlationId) {
346
+ async function checkTimeOut({
347
+ correlationId
348
+ }) {
251
349
  const {
252
350
  modificationTime,
253
- queueitemState: oldState
351
+ queueitemState: oldState,
352
+ importJobState
254
353
  } = await db.collection(collection).findOne({
255
354
  correlationId
256
- });
355
+ }); // should we check for DONE too?
257
356
 
258
- if ([_constants.QUEUE_ITEM_STATE.ABORT, _constants.QUEUE_ITEM_STATE.ERROR].includes(oldState)) {
357
+ if ([_constants.QUEUE_ITEM_STATE.ABORT, _constants.QUEUE_ITEM_STATE.ERROR, _constants.QUEUE_ITEM_STATE.DONE].includes(oldState)) {
259
358
  logger.silly(`${correlationId} has already state: ${oldState}`);
260
359
  return false;
261
360
  }
@@ -264,6 +363,26 @@ async function _default(MONGO_URI, collection) {
264
363
  logger.silly(`timeOut @ ${timeoutTime}`);
265
364
 
266
365
  if (timeoutTime.isBefore()) {
366
+ const finalImportJobStates = [_constants.IMPORT_JOB_STATE.ABORT, _constants.IMPORT_JOB_STATE.DONE, _constants.IMPORT_JOB_STATE.EMPTY, _constants.IMPORT_JOB_STATE.ERROR];
367
+
368
+ if (!finalImportJobStates.includes(importJobState.CREATE)) {
369
+ // eslint-disable-line
370
+ await setImportJobState({
371
+ correlationId,
372
+ operation: 'CREATE',
373
+ importJobState: _constants.IMPORT_JOB_STATE.ABORT
374
+ });
375
+ }
376
+
377
+ if (!finalImportJobStates.includes(importJobState.UPDATE)) {
378
+ // eslint-disable-line
379
+ await setImportJobState({
380
+ correlationId,
381
+ operation: 'UPDATE',
382
+ importJobState: _constants.IMPORT_JOB_STATE.ABORT
383
+ });
384
+ }
385
+
267
386
  await setState({
268
387
  correlationId,
269
388
  state: _constants.QUEUE_ITEM_STATE.ABORT,
@@ -319,13 +438,26 @@ async function _default(MONGO_URI, collection) {
319
438
  }); // njsscan-ignore: node_nosqli_injection
320
439
 
321
440
  if (result) {
322
- return {
323
- contentType: result.contentType,
324
- readStream: gridFSBucket.openDownloadStreamByName(clean)
325
- };
441
+ const {
442
+ operationSettings
443
+ } = result;
444
+
445
+ if (operationSettings.prio === false && operationSettings.noStream === false) {
446
+ return {
447
+ contentType: result.contentType,
448
+ readStream: gridFSBucket.openDownloadStreamByName(clean)
449
+ };
450
+ }
451
+
452
+ logger.debug(`OperationSetting for ${correlationId}: ${JSON.stringify(operationSettings)}`);
453
+ throw new _melindaCommons.Error(_httpStatus.default.BAD_REQUEST, {
454
+ message: `Content is only available for streamBulk jobs. ${correlationId} is not a streamBulk job.`
455
+ });
326
456
  }
327
457
 
328
- throw new _melindaCommons.Error(_httpStatus.default.NOT_FOUND);
458
+ throw new _melindaCommons.Error(_httpStatus.default.NOT_FOUND, {
459
+ message: `Job ${correlationId} not found.`
460
+ });
329
461
  }
330
462
 
331
463
  async function removeContent(params) {
@@ -343,30 +475,43 @@ async function _default(MONGO_URI, collection) {
343
475
  }
344
476
 
345
477
  return true;
346
- }
478
+ } // eslint-disable-next-line max-statements
479
+
347
480
 
348
481
  function getOne({
349
- operation,
350
- queueItemState
482
+ queueItemState,
483
+ importJobState = undefined
351
484
  }) {
352
- const clean = {
485
+ logger.silly(`queueItemState: ${queueItemState}, importJobState: ${JSON.stringify(importJobState)}`);
486
+ const cleanQueueItemState = queueItemState ? {
353
487
  queueItemState: (0, _mongoSanitize.default)(queueItemState)
354
- };
488
+ } : undefined;
355
489
 
356
490
  try {
357
- if (operation === undefined) {
358
- logger.silly(`Checking DB ${collection} for ${JSON.stringify(clean.queueItemState)}`);
359
- return db.collection(collection).findOne({ ...clean
491
+ // Just queueItemState
492
+ if (queueItemState && importJobState === undefined) {
493
+ logger.silly(`Checking DB ${collection} for just ${JSON.stringify(cleanQueueItemState.queueItemState)}`);
494
+ return db.collection(collection).findOne({ ...cleanQueueItemState
495
+ });
496
+ } // importJobState
497
+
498
+
499
+ if (importJobState && queueItemState === undefined) {
500
+ logger.silly(`Checking DB ${collection} for ${JSON.stringify(importJobState)}`);
501
+ return db.collection(collection).findOne({ ...importJobState
502
+ });
503
+ } // importJobState and queueItemState
504
+
505
+
506
+ if (importJobState && queueItemState) {
507
+ logger.silly(`Checking DB ${collection} for ${queueItemState} and ${JSON.stringify(importJobState)}`);
508
+ return db.collection(collection).findOne({ ...cleanQueueItemState,
509
+ ...importJobState
360
510
  });
361
511
  }
362
512
 
363
- const clean2 = {
364
- operation: (0, _mongoSanitize.default)(operation)
365
- };
366
- logger.silly(`Checking DB ${collection} for ${clean.queueItemState} + ${clean2.operation}`);
367
- return db.collection(collection).findOne({ ...clean,
368
- ...clean2
369
- });
513
+ logger.debug(`getOne not working!`);
514
+ throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR, 'Missing parameters, cannot get queueItem');
370
515
  } catch (error) {
371
516
  (0, _utils.logError)(error);
372
517
  }
@@ -469,5 +614,150 @@ async function _default(MONGO_URI, collection) {
469
614
  returnNewDocument: true
470
615
  });
471
616
  }
617
+
618
+ function setImportJobState({
619
+ correlationId,
620
+ operation,
621
+ importJobState
622
+ }) {
623
+ // should this also get importJobState as previously created object? {}
624
+ logger.info(`Setting queue-item importJobState: {${operation}: ${importJobState}} for ${correlationId}`);
625
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
626
+ const cleanImportJobState = (0, _mongoSanitize.default)(importJobState);
627
+
628
+ if (!(operation in _constants.OPERATIONS)) {
629
+ throw new _melindaCommons.Error('400', 'Invalid operation for import job state');
630
+ }
631
+
632
+ if (!(cleanImportJobState in _constants.IMPORT_JOB_STATE)) {
633
+ throw new _melindaCommons.Error('400', 'Invalid import job state');
634
+ }
635
+
636
+ const newJobState = operation === _constants.OPERATIONS.CREATE ? {
637
+ 'importJobState.CREATE': cleanImportJobState
638
+ } : {
639
+ 'importJobState.UPDATE': cleanImportJobState
640
+ };
641
+ return db.collection(collection).findOneAndUpdate({
642
+ correlationId: cleanCorrelationId
643
+ }, {
644
+ $set: { ...newJobState,
645
+ modificationTime: (0, _moment.default)().toDate()
646
+ }
647
+ }, {
648
+ projection: {
649
+ _id: 0
650
+ },
651
+ returnNewDocument: true
652
+ });
653
+ }
654
+
655
+ async function setOperation({
656
+ correlationId,
657
+ operation
658
+ }) {
659
+ const newOperation = operation;
660
+ const {
661
+ operation: oldOperation
662
+ } = await db.collection(collection).findOne({
663
+ correlationId
664
+ });
665
+ logger.info(`Setting queue-item operation from ${oldOperation} to ${newOperation} for ${correlationId} to ${collection}`);
666
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
667
+ const cleanNewOperation = (0, _mongoSanitize.default)(newOperation);
668
+ const result = await db.collection(collection).findOneAndUpdate({
669
+ correlationId: cleanCorrelationId
670
+ }, {
671
+ $set: {
672
+ operation: cleanNewOperation,
673
+ modificationTime: (0, _moment.default)().toDate()
674
+ }
675
+ }, {
676
+ projection: {
677
+ _id: 0
678
+ },
679
+ returnNewDocument: true
680
+ });
681
+ return result.ok; // logger.debug(JSON.stringify(result));
682
+ }
683
+
684
+ async function setOperations({
685
+ correlationId,
686
+ addOperation,
687
+ removeOperation = undefined
688
+ }) {
689
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
690
+ const queueItem = await db.collection(collection).findOne({
691
+ correlationId: cleanCorrelationId
692
+ });
693
+ logger.silly(`We found a queueItem: ${JSON.stringify(queueItem)}`);
694
+ const oldOperations = queueItem.operations;
695
+ logger.info(`Setting queue-item operations from ${JSON.stringify(oldOperations)} by adding ${addOperation} and removing ${removeOperation} for ${correlationId} to ${collection}`);
696
+ const operationsAfterRemove = oldOperations.filter(operation => operation !== removeOperation);
697
+ const operationsAfterRemoveAndAdd = operationsAfterRemove.includes(addOperation) ? operationsAfterRemove : [...operationsAfterRemove, addOperation];
698
+ logger.silly(`operationsAfterRemove: ${operationsAfterRemove}`);
699
+ logger.silly(`operationAfterRemoveAndAdd: ${operationsAfterRemoveAndAdd}`);
700
+ const result = await db.collection(collection).findOneAndUpdate({
701
+ correlationId: cleanCorrelationId
702
+ }, {
703
+ $set: {
704
+ operations: operationsAfterRemoveAndAdd,
705
+ modificationTime: (0, _moment.default)().toDate()
706
+ }
707
+ }, {
708
+ projection: {
709
+ _id: 0
710
+ },
711
+ returnNewDocument: true
712
+ });
713
+ return result.ok; // logger.debug(JSON.stringify(result));
714
+ }
715
+
716
+ async function addBlobSize({
717
+ correlationId
718
+ }) {
719
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
720
+ const result = await db.collection(collection).findOneAndUpdate({
721
+ correlationId: cleanCorrelationId,
722
+ queueItemState: _constants.QUEUE_ITEM_STATE.VALIDATOR.WAITING_FOR_RECORDS
723
+ }, {
724
+ $inc: {
725
+ blobSize: 1
726
+ },
727
+ $set: {
728
+ modificationTime: (0, _moment.default)().toDate()
729
+ }
730
+ }, {
731
+ projection: {
732
+ _id: 0
733
+ },
734
+ returnNewDocument: true
735
+ });
736
+ logger.verbose(`AddBlobSizeResult in mongo: ${JSON.stringify(result)}`);
737
+ return result;
738
+ }
739
+
740
+ async function setBlobSize({
741
+ correlationId,
742
+ blobSize
743
+ }) {
744
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
745
+ const cleanBlobSize = (0, _mongoSanitize.default)(blobSize);
746
+ const result = await db.collection(collection).findOneAndUpdate({
747
+ correlationId: cleanCorrelationId
748
+ }, {
749
+ $set: {
750
+ blobSize: cleanBlobSize,
751
+ modificationTime: (0, _moment.default)().toDate()
752
+ }
753
+ }, {
754
+ projection: {
755
+ _id: 0
756
+ },
757
+ returnNewDocument: true
758
+ });
759
+ logger.verbose(`SetBlobSizeResult in mongo: ${JSON.stringify(result)}`);
760
+ return result;
761
+ }
472
762
  }
473
763
  //# sourceMappingURL=mongo.js.map