@natlibfi/melinda-rest-api-commons 2.1.3 → 2.2.0-alpha.11

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
@@ -57,6 +57,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
57
57
  "cataloger":"xxx0000",
58
58
  "oCatalogerIn":"xxx0000"
59
59
  "operation":"UPDATE",
60
+ "operations":["UPDATE", "CREATE"]
60
61
  "contentType":"application/json",
61
62
  "recordLoadParams": {
62
63
  "pActiveLibrary": "XXX00",
@@ -66,6 +67,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
66
67
  "pOldNew": "NEW"
67
68
  },
68
69
  "queueItemState":"PENDING_QUEUING",
70
+ "importJobState": {
71
+ "CREATE": "EMPTY",
72
+ "UPDATE": "EMPTY"
73
+ },
69
74
  "creationTime":"2020-01-01T00:00:00.000Z",
70
75
  "modificationTime":"2020-01-01T00:00:01.000Z",
71
76
  "handledIds": []
@@ -86,6 +91,7 @@ async function _default(MONGO_URI, collection) {
86
91
  createPrio,
87
92
  createBulk,
88
93
  checkAndSetState,
94
+ checkAndSetImportJobState,
89
95
  query,
90
96
  queryById,
91
97
  remove,
@@ -94,8 +100,13 @@ async function _default(MONGO_URI, collection) {
94
100
  getOne,
95
101
  getStream,
96
102
  setState,
103
+ setImportJobState,
97
104
  pushIds,
98
- pushMessages
105
+ pushMessages,
106
+ setOperation,
107
+ setOperations,
108
+ addBlobSize,
109
+ setBlobSize
99
110
  };
100
111
 
101
112
  async function createPrio({
@@ -103,22 +114,25 @@ async function _default(MONGO_URI, collection) {
103
114
  cataloger,
104
115
  oCatalogerIn,
105
116
  operation,
106
- noop = undefined,
107
- unique = undefined,
108
- prio = true
117
+ operationSettings
109
118
  }) {
110
119
  const time = (0, _moment.default)().toDate();
111
120
  const newQueueItem = {
112
121
  correlationId,
113
122
  cataloger,
114
123
  operation,
124
+ operations: [operation],
115
125
  oCatalogerIn,
116
126
  operationSettings: {
117
- unique,
118
- noop,
119
- prio
127
+ prio: true,
128
+ ...operationSettings
120
129
  },
121
130
  queueItemState: _constants.QUEUE_ITEM_STATE.VALIDATOR.PENDING_VALIDATION,
131
+ importJobState: {
132
+ CREATE: _constants.IMPORT_JOB_STATE.EMPTY,
133
+ UPDATE: _constants.IMPORT_JOB_STATE.EMPTY
134
+ },
135
+ blobSize: 1,
122
136
  creationTime: time,
123
137
  modificationTime: time,
124
138
  handledIds: [],
@@ -140,7 +154,7 @@ async function _default(MONGO_URI, collection) {
140
154
  }
141
155
  }
142
156
 
143
- function createBulk({
157
+ async function createBulk({
144
158
  correlationId,
145
159
  cataloger,
146
160
  oCatalogerIn,
@@ -148,7 +162,7 @@ async function _default(MONGO_URI, collection) {
148
162
  contentType,
149
163
  recordLoadParams,
150
164
  stream,
151
- prio = false
165
+ operationSettings
152
166
  }) {
153
167
  const time = (0, _moment.default)().toDate();
154
168
  const newQueueItem = {
@@ -156,45 +170,76 @@ async function _default(MONGO_URI, collection) {
156
170
  cataloger,
157
171
  oCatalogerIn,
158
172
  operation,
173
+ operations: [operation],
159
174
  operationSettings: {
160
- prio
175
+ prio: false,
176
+ ...operationSettings
161
177
  },
162
178
  contentType,
163
179
  recordLoadParams,
164
- queueItemState: _constants.QUEUE_ITEM_STATE.VALIDATOR.UPLOADING,
180
+ queueItemState: stream ? _constants.QUEUE_ITEM_STATE.VALIDATOR.UPLOADING : _constants.QUEUE_ITEM_STATE.VALIDATOR.WAITING_FOR_RECORDS,
181
+ blobSize: 0,
182
+ importJobState: {
183
+ CREATE: _constants.IMPORT_JOB_STATE.EMPTY,
184
+ UPDATE: _constants.IMPORT_JOB_STATE.EMPTY
185
+ },
165
186
  creationTime: time,
166
187
  modificationTime: time,
167
188
  handledIds: [],
168
189
  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);
190
+ }; // eslint-disable-next-line functional/no-conditional-statement
191
+
192
+ if (stream) {
193
+ try {
194
+ // No await here, promises later
195
+ db.collection(collection).insertOne(newQueueItem);
196
+ logger.info(`New BULK queue item for ${operation} ${correlationId} has been made in ${collection}!`);
197
+ return new Promise((resolve, reject) => {
198
+ const outputStream = gridFSBucket.openUploadStream(correlationId);
199
+ stream.on('error', reject).on('data', chunk => outputStream.write(chunk)).on('end', () => outputStream.end(undefined, undefined, () => {
200
+ resolve(correlationId);
201
+ }));
202
+ });
203
+ } catch (error) {
204
+ (0, _utils.logError)(error);
205
+ throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR);
206
+ }
178
207
  }
179
208
 
180
- return new Promise((resolve, reject) => {
181
- const outputStream = gridFSBucket.openUploadStream(correlationId);
182
- stream.on('error', reject).on('data', chunk => outputStream.write(chunk)).on('end', () => outputStream.end(undefined, undefined, () => {
183
- resolve(correlationId);
184
- }));
185
- });
209
+ logger.debug(`No stream`); // eslint-disable-next-line functional/no-conditional-statement
210
+
211
+ if (!stream) {
212
+ try {
213
+ const result = await db.collection(collection).insertOne(newQueueItem);
214
+
215
+ if (result.acknowledged) {
216
+ logger.info(`New noStream BULK queue item for ${operation} ${correlationId} has been made in ${collection}`);
217
+ return {
218
+ correlationId,
219
+ queueItemState: _constants.QUEUE_ITEM_STATE.VALIDATOR.WAITING_FOR_RECORDS
220
+ };
221
+ }
222
+
223
+ throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR);
224
+ } catch (error) {
225
+ (0, _utils.logError)(error);
226
+ throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR);
227
+ }
228
+ }
186
229
  } // Check state that the queueItem has not waited too long and set state
187
230
 
188
231
 
189
232
  async function checkAndSetState({
190
233
  correlationId,
191
234
  state,
192
- errorMessage = '',
193
- errorStatus = ''
235
+ errorMessage = undefined,
236
+ errorStatus = undefined
194
237
  }) {
195
238
  // checkTimeOut returns true, if queueItem is fresher than 1 minute and it's state is not ABORT/ERROR
196
239
  // otherwise it sets queueItem to state ABORT (408, 'Timeout')
197
- const timeOut = await checkTimeOut(correlationId);
240
+ const timeOut = await checkTimeOut({
241
+ correlationId
242
+ });
198
243
 
199
244
  if (timeOut) {
200
245
  return setState({
@@ -205,6 +250,36 @@ async function _default(MONGO_URI, collection) {
205
250
  });
206
251
  }
207
252
 
253
+ return false;
254
+ } // Check state that the queueItem has not waited too long and set state
255
+
256
+
257
+ async function checkAndSetImportJobState({
258
+ correlationId,
259
+ operation,
260
+ importJobState,
261
+ errorMessage = '',
262
+ errorStatus = ''
263
+ }) {
264
+ // checkTimeOut returns true, if queueItem is fresher than 1 minute and it's state is not ABORT/ERROR
265
+ // otherwise it sets queueItem to state ABORT (408, 'Timeout')
266
+ logger.debug(`${correlationId}, ${importJobState}, ${operation}`);
267
+ const timeOut = await checkTimeOut({
268
+ correlationId,
269
+ operation,
270
+ importJobState
271
+ });
272
+
273
+ if (timeOut) {
274
+ return setImportJobState({
275
+ correlationId,
276
+ operation,
277
+ importJobState,
278
+ errorMessage,
279
+ errorStatus
280
+ });
281
+ }
282
+
208
283
  return false;
209
284
  }
210
285
 
@@ -218,16 +293,23 @@ async function _default(MONGO_URI, collection) {
218
293
  return result;
219
294
  }
220
295
 
221
- async function queryById(correlationId, checkModTime) {
296
+ async function queryById({
297
+ correlationId,
298
+ checkModTime = false
299
+ }) {
222
300
  const result = await db.collection(collection).findOne({
223
301
  correlationId
224
302
  });
225
303
 
226
304
  if (checkModTime) {
227
- const timeOut = await checkTimeOut(correlationId);
305
+ const timeOut = await checkTimeOut({
306
+ correlationId
307
+ });
228
308
 
229
309
  if (timeOut) {
230
- return queryById(correlationId);
310
+ return queryById({
311
+ correlationId
312
+ });
231
313
  }
232
314
 
233
315
  return result;
@@ -240,15 +322,18 @@ async function _default(MONGO_URI, collection) {
240
322
  // If the state is already ABORT or ERROR return false
241
323
 
242
324
 
243
- async function checkTimeOut(correlationId) {
325
+ async function checkTimeOut({
326
+ correlationId
327
+ }) {
244
328
  const {
245
329
  modificationTime,
246
- queueitemState: oldState
330
+ queueitemState: oldState,
331
+ importJobState
247
332
  } = await db.collection(collection).findOne({
248
333
  correlationId
249
- });
334
+ }); // should we check for DONE too?
250
335
 
251
- if ([_constants.QUEUE_ITEM_STATE.ABORT, _constants.QUEUE_ITEM_STATE.ERROR].includes(oldState)) {
336
+ if ([_constants.QUEUE_ITEM_STATE.ABORT, _constants.QUEUE_ITEM_STATE.ERROR, _constants.QUEUE_ITEM_STATE.DONE].includes(oldState)) {
252
337
  logger.silly(`${correlationId} has already state: ${oldState}`);
253
338
  return false;
254
339
  }
@@ -257,6 +342,26 @@ async function _default(MONGO_URI, collection) {
257
342
  logger.silly(`timeOut @ ${timeoutTime}`);
258
343
 
259
344
  if (timeoutTime.isBefore()) {
345
+ const finalImportJobStates = [_constants.IMPORT_JOB_STATE.ABORT, _constants.IMPORT_JOB_STATE.DONE, _constants.IMPORT_JOB_STATE.EMPTY, _constants.IMPORT_JOB_STATE.ERROR];
346
+
347
+ if (!finalImportJobStates.includes(importJobState.CREATE)) {
348
+ // eslint-disable-line
349
+ await setImportJobState({
350
+ correlationId,
351
+ operation: 'CREATE',
352
+ importJobState: _constants.IMPORT_JOB_STATE.ABORT
353
+ });
354
+ }
355
+
356
+ if (!finalImportJobStates.includes(importJobState.UPDATE)) {
357
+ // eslint-disable-line
358
+ await setImportJobState({
359
+ correlationId,
360
+ operation: 'UPDATE',
361
+ importJobState: _constants.IMPORT_JOB_STATE.ABORT
362
+ });
363
+ }
364
+
260
365
  await setState({
261
366
  correlationId,
262
367
  state: _constants.QUEUE_ITEM_STATE.ABORT,
@@ -336,30 +441,43 @@ async function _default(MONGO_URI, collection) {
336
441
  }
337
442
 
338
443
  return true;
339
- }
444
+ } // eslint-disable-next-line max-statements
445
+
340
446
 
341
447
  function getOne({
342
- operation,
343
- queueItemState
448
+ queueItemState,
449
+ importJobState = undefined
344
450
  }) {
345
- const clean = {
451
+ logger.silly(`queueItemState: ${queueItemState}, importJobState: ${JSON.stringify(importJobState)}`);
452
+ const cleanQueueItemState = queueItemState ? {
346
453
  queueItemState: (0, _mongoSanitize.default)(queueItemState)
347
- };
454
+ } : undefined;
348
455
 
349
456
  try {
350
- if (operation === undefined) {
351
- logger.silly(`Checking DB ${collection} for ${JSON.stringify(clean.queueItemState)}`);
352
- return db.collection(collection).findOne({ ...clean
457
+ // Just queueItemState
458
+ if (queueItemState && importJobState === undefined) {
459
+ logger.silly(`Checking DB ${collection} for just ${JSON.stringify(cleanQueueItemState.queueItemState)}`);
460
+ return db.collection(collection).findOne({ ...cleanQueueItemState
461
+ });
462
+ } // importJobState
463
+
464
+
465
+ if (importJobState && queueItemState === undefined) {
466
+ logger.silly(`Checking DB ${collection} for ${JSON.stringify(importJobState)}`);
467
+ return db.collection(collection).findOne({ ...importJobState
468
+ });
469
+ } // importJobState and queueItemState
470
+
471
+
472
+ if (importJobState && queueItemState) {
473
+ logger.silly(`Checking DB ${collection} for ${queueItemState} and ${JSON.stringify(importJobState)}`);
474
+ return db.collection(collection).findOne({ ...cleanQueueItemState,
475
+ ...importJobState
353
476
  });
354
477
  }
355
478
 
356
- const clean2 = {
357
- operation: (0, _mongoSanitize.default)(operation)
358
- };
359
- logger.silly(`Checking DB ${collection} for ${clean.queueItemState} + ${clean2.operation}`);
360
- return db.collection(collection).findOne({ ...clean,
361
- ...clean2
362
- });
479
+ logger.debug(`getOne not working!`);
480
+ throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR, 'Missing parameters, cannot get queueItem');
363
481
  } catch (error) {
364
482
  (0, _utils.logError)(error);
365
483
  }
@@ -428,20 +546,97 @@ async function _default(MONGO_URI, collection) {
428
546
  function setState({
429
547
  correlationId,
430
548
  state,
431
- errorMessage = '',
432
- errorStatus = ''
549
+ errorMessage = undefined,
550
+ errorStatus = undefined
433
551
  }) {
434
- const errorString = errorMessage || errorStatus ? `, Error message: '${errorMessage}', Error status: '${errorStatus}'` : '';
552
+ const errorString = errorMessage || errorStatus ? `, Error message: '${errorMessage || ''}', Error status: '${errorStatus || ''}'` : '';
435
553
  logger.info(`Setting queue-item state ${state} for ${correlationId}${errorString} to ${collection}`);
554
+ const stateInQueueItemStates = Object.values(_constants.QUEUE_ITEM_STATE).indexOf(state) > -1;
555
+ const stateInQueueItemStatesValidator = Object.values(_constants.QUEUE_ITEM_STATE.VALIDATOR).indexOf(state) > -1;
556
+ const stateInQueueItemStatesImporter = Object.values(_constants.QUEUE_ITEM_STATE.IMPORTER).indexOf(state) > -1;
557
+
558
+ if (!stateInQueueItemStates && !stateInQueueItemStatesValidator && !stateInQueueItemStatesImporter) {
559
+ throw new _melindaCommons.Error(_httpStatus.default.BAD_REQUEST, 'Trying to set invalid state');
560
+ }
561
+
436
562
  const clean = (0, _mongoSanitize.default)(correlationId);
563
+ const updateValues = {
564
+ queueItemState: state,
565
+ modificationTime: (0, _moment.default)().toDate(),
566
+ errorMessage,
567
+ errorStatus
568
+ }; // Do not update value that are undefined
569
+ // eslint-disable-next-line functional/immutable-data
570
+
571
+ Object.keys(updateValues).forEach(key => updateValues[key] === undefined && delete updateValues[key]);
437
572
  return db.collection(collection).findOneAndUpdate({
438
573
  correlationId: clean
574
+ }, {
575
+ $set: updateValues
576
+ }, {
577
+ projection: {
578
+ _id: 0
579
+ },
580
+ returnNewDocument: true
581
+ });
582
+ }
583
+
584
+ function setImportJobState({
585
+ correlationId,
586
+ operation,
587
+ importJobState
588
+ }) {
589
+ // should this also get importJobState as previously created object? {}
590
+ logger.info(`Setting queue-item importJobState: {${operation}: ${importJobState}} for ${correlationId}`);
591
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
592
+ const cleanImportJobState = (0, _mongoSanitize.default)(importJobState);
593
+
594
+ if (!(operation in _constants.OPERATIONS)) {
595
+ throw new _melindaCommons.Error('400', 'Invalid operation for import job state');
596
+ }
597
+
598
+ if (!(cleanImportJobState in _constants.IMPORT_JOB_STATE)) {
599
+ throw new _melindaCommons.Error('400', 'Invalid import job state');
600
+ }
601
+
602
+ const newJobState = operation === _constants.OPERATIONS.CREATE ? {
603
+ 'importJobState.CREATE': cleanImportJobState
604
+ } : {
605
+ 'importJobState.UPDATE': cleanImportJobState
606
+ };
607
+ return db.collection(collection).findOneAndUpdate({
608
+ correlationId: cleanCorrelationId
609
+ }, {
610
+ $set: { ...newJobState,
611
+ modificationTime: (0, _moment.default)().toDate()
612
+ }
613
+ }, {
614
+ projection: {
615
+ _id: 0
616
+ },
617
+ returnNewDocument: true
618
+ });
619
+ }
620
+
621
+ async function setOperation({
622
+ correlationId,
623
+ operation
624
+ }) {
625
+ const newOperation = operation;
626
+ const {
627
+ operation: oldOperation
628
+ } = await db.collection(collection).findOne({
629
+ correlationId
630
+ });
631
+ logger.info(`Setting queue-item operation from ${oldOperation} to ${newOperation} for ${correlationId} to ${collection}`);
632
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
633
+ const cleanNewOperation = (0, _mongoSanitize.default)(newOperation);
634
+ const result = await db.collection(collection).findOneAndUpdate({
635
+ correlationId: cleanCorrelationId
439
636
  }, {
440
637
  $set: {
441
- queueItemState: state,
442
- modificationTime: (0, _moment.default)().toDate(),
443
- errorMessage,
444
- errorStatus
638
+ operation: cleanNewOperation,
639
+ modificationTime: (0, _moment.default)().toDate()
445
640
  }
446
641
  }, {
447
642
  projection: {
@@ -449,6 +644,85 @@ async function _default(MONGO_URI, collection) {
449
644
  },
450
645
  returnNewDocument: true
451
646
  });
647
+ return result.ok; // logger.debug(JSON.stringify(result));
648
+ }
649
+
650
+ async function setOperations({
651
+ correlationId,
652
+ addOperation,
653
+ removeOperation = undefined
654
+ }) {
655
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId); //logger.info(`Setting queue-item operation from ${JSON.stringify(oldOperations)} by adding ${addOperation} and removing ${removeOperation} for ${correlationId} to ${collection}`);
656
+
657
+ const queueItem = await db.collection(collection).findOne({
658
+ correlationId: cleanCorrelationId
659
+ });
660
+ logger.debug(`We fould a queueItem: ${JSON.stringify(queueItem)}`);
661
+ const oldOperations = queueItem.operations;
662
+ logger.info(`Setting queue-item operation from ${JSON.stringify(oldOperations)} by adding ${addOperation} and removing ${removeOperation} for ${correlationId} to ${collection}`);
663
+ const operationsAfterRemove = oldOperations.filter(operation => operation !== removeOperation);
664
+ const operationsAfterRemoveAndAdd = [addOperation, ...operationsAfterRemove];
665
+ const result = await db.collection(collection).findOneAndUpdate({
666
+ correlationId: cleanCorrelationId
667
+ }, {
668
+ $set: {
669
+ operations: operationsAfterRemoveAndAdd,
670
+ modificationTime: (0, _moment.default)().toDate()
671
+ }
672
+ }, {
673
+ projection: {
674
+ _id: 0
675
+ },
676
+ returnNewDocument: true
677
+ });
678
+ return result.ok; // logger.debug(JSON.stringify(result));
679
+ }
680
+
681
+ async function addBlobSize({
682
+ correlationId
683
+ }) {
684
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
685
+ const result = await db.collection(collection).findOneAndUpdate({
686
+ correlationId: cleanCorrelationId,
687
+ queueItemState: _constants.QUEUE_ITEM_STATE.VALIDATOR.WAITING_FOR_RECORDS
688
+ }, {
689
+ $inc: {
690
+ blobSize: 1
691
+ },
692
+ $set: {
693
+ modificationTime: (0, _moment.default)().toDate()
694
+ }
695
+ }, {
696
+ projection: {
697
+ _id: 0
698
+ },
699
+ returnNewDocument: true
700
+ });
701
+ logger.verbose(`AddBlobSizeResult in mongo: ${JSON.stringify(result)}`);
702
+ return result;
703
+ }
704
+
705
+ async function setBlobSize({
706
+ correlationId,
707
+ blobSize
708
+ }) {
709
+ const cleanCorrelationId = (0, _mongoSanitize.default)(correlationId);
710
+ const cleanBlobSize = (0, _mongoSanitize.default)(blobSize);
711
+ const result = await db.collection(collection).findOneAndUpdate({
712
+ correlationId: cleanCorrelationId
713
+ }, {
714
+ $set: {
715
+ blobSize: cleanBlobSize,
716
+ modificationTime: (0, _moment.default)().toDate()
717
+ }
718
+ }, {
719
+ projection: {
720
+ _id: 0
721
+ },
722
+ returnNewDocument: true
723
+ });
724
+ logger.verbose(`SetBlobSizeResult in mongo: ${JSON.stringify(result)}`);
725
+ return result;
452
726
  }
453
727
  }
454
728
  //# sourceMappingURL=mongo.js.map