4
4
*
5
5
* Shared modules for microservices of Melinda rest api batch import system
6
6
*
7
- * Copyright (C) 2020-2022 University Of Helsinki (The National Library Of Finland)
7
+ * Copyright (C) 2020-2023 University Of Helsinki (The National Library Of Finland)
8
8
*
9
9
* This file is part of melinda-rest-api-commons
10
10
*
@@ -35,6 +35,12 @@ import httpStatus from 'http-status';
35
35
import sanitize from 'mongo-sanitize' ;
36
36
import { LOG_ITEM_TYPE } from './constants' ;
37
37
38
+ /**
39
+ * Create log operator
40
+ * @param {String } MONGO_URI connnection address to mongo
41
+ * @param {String } dbName Mongo DB name, defaults 'rest-api'
42
+ * @returns {Object } containing all log handling functions
43
+ */
38
44
export default async function ( MONGO_URI , dbName = 'rest-api' ) {
39
45
const logger = createLogger ( ) ;
40
46
@@ -44,6 +50,11 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
44
50
const collection = 'logs' ;
45
51
return { addLogItem, query, queryById, getListOfLogs, getListOfCatalogers, getExpandedListOfLogs, protect, remove, removeBySequences} ;
46
52
53
+ /**
54
+ * Add log item to collection
55
+ * @param {Object } logItem contains log item data
56
+ * @returns void
57
+ */
47
58
async function addLogItem ( logItem ) {
48
59
const time = moment ( ) . toDate ( ) ;
49
60
const newLogItem = {
@@ -70,11 +81,17 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
70
81
}
71
82
}
72
83
73
- async function query ( params ) {
74
- logger . debug ( `Query params: ${ JSON . stringify ( params ) } ` ) ;
75
- checkLogItemType ( params . logItemType , false , false ) ;
76
- const { limit = 5 , skip = 0 , ...rest } = params ;
77
- logger . debug ( `Actual query params: ${ JSON . stringify ( rest ) } ` ) ;
84
+ /**
85
+ * Query log items
86
+ * @param {Integer } limit defaults 5
87
+ * @param {Integer } skip defaults 0
88
+ * @param {Object } rest query params
89
+ * @returns result array
90
+ */
91
+ async function query ( { limit = 5 , skip = 0 , ...rest } ) {
92
+ logger . debug ( `Query params: ${ JSON . stringify ( rest ) } ` ) ;
93
+ logger . debug ( `Limit and skip params: ${ limit } | ${ skip } ` ) ;
94
+ checkLogItemType ( rest . logItemType , false , false ) ;
78
95
const result = await db . collection ( collection ) // eslint-disable-line functional/immutable-data
79
96
. find ( rest )
80
97
. sort ( { creationTime : 1 } )
@@ -87,10 +104,18 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
87
104
}
88
105
89
106
// DEVELOP: queryById returns jsut one (randomish) log! is this useful?
90
- async function queryById ( correlationIdString , skip = 0 , limit = 1 ) {
91
- logger . debug ( `QueryById: ${ correlationIdString } ` ) ;
107
+ /**
108
+ * Get single log item by correlationId
109
+ * @param {String } correlationId
110
+ * @param {String } logItemType constant LOG_ITEM_TYPE defaults LOG_ITEM_TYPE.MERGE_LOG
111
+ * @param {Integer } skip defaults 0
112
+ * @param {Integer } limit defaults 1
113
+ * @returns query result array
114
+ */
115
+ async function queryById ( correlationId , logItemType = LOG_ITEM_TYPE . MERGE_LOG , skip = 0 , limit = 1 ) {
116
+ logger . debug ( `QueryById: ${ correlationId } ` ) ;
92
117
const result = await db . collection ( collection ) // eslint-disable-line functional/immutable-data
93
- . find ( { correlationId : correlationIdString } )
118
+ . find ( { correlationId, logItemType } )
94
119
. sort ( { blobSequence : 1 } )
95
120
. skip ( parseInt ( skip , 10 ) )
96
121
. limit ( parseInt ( limit , 10 ) )
@@ -101,14 +126,23 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
101
126
102
127
// getListOfLogs returns list of correlationIds that have logs of given logItemType
103
128
// if logItemType is not given, getListOfLogs returns list of correlationIds that have MERGE_LOG
104
- async function getListOfLogs ( logItemType = 'MERGE_LOG' ) {
105
- checkLogItemType ( logItemType , false , false ) ;
129
+ /**
130
+ * Get list of correlationIds of logs filtered by logItemType
131
+ * @param {String } logItemType constant LOG_ITEM_TYPE defaults LOG_ITEM_TYPE.MERGE_LOG
132
+ * @returns Array of query results
133
+ */
134
+ async function getListOfLogs ( logItemType = LOG_ITEM_TYPE . MERGE_LOG ) {
135
+ // checkLogItemType(logItemType, false, false);
106
136
const result = await db . collection ( collection ) // eslint-disable-line functional/immutable-data
107
137
. distinct ( 'correlationId' , { logItemType} ) ;
108
138
logger . debug ( `Query result: ${ result . length > 0 ? `Found ${ result . length } log items!` : 'Not found!' } ` ) ;
109
- return { status : result . length > 0 ? httpStatus . OK : httpStatus . NOT_FOUND , payload : result . length > 0 ? result : 'No logs found' } ;
139
+ return result ;
110
140
}
111
141
142
+ /**
143
+ * Get list of catalogers from logs
144
+ * @returns Array of query results
145
+ */
112
146
async function getListOfCatalogers ( ) {
113
147
logger . debug ( `Getting list of Catalogers` ) ;
114
148
@@ -118,15 +152,23 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
118
152
return result ;
119
153
}
120
154
121
- // getExpandedListOfLogs returns groped MERGE_LOGs and MATCH_LOGs
122
- async function getExpandedListOfLogs ( { logItemTypes = [ LOG_ITEM_TYPE . MERGE_LOG , LOG_ITEM_TYPE . MATCH_LOG ] , catalogers = [ ] , dateBefore = new Date ( ) , dateAfter = new Date ( '2000-01-01' ) } ) {
155
+ /**
156
+ * Get filtered list of logs with extra info. Give params in Object
157
+ * @param {[String] } logItemTypes: String array of logItemTypes. Defaults [LOG_ITEM_TYPE.MERGE_LOG, LOG_ITEM_TYPE.MATCH_LOG]
158
+ * @param {[String] } catalogers: String array of wanted catalogers. Defaults []
159
+ * @param {String } dateBefore: String date schema 'YYYY-MM-DD'. Defaults new Date()
160
+ * @param {String } dateAfter: String date schema 'YYYY-MM-DD'. Defaults '2000-01-01'
161
+ * @param {Boolean } test: Boolean is this test run. Defaults false
162
+ * @returns Parsed Object {'correlationId', 'logItemType', 'creationTime', 'cataloger', 'logCount'}
163
+ */
164
+ async function getExpandedListOfLogs ( { logItemTypes = [ LOG_ITEM_TYPE . MERGE_LOG , LOG_ITEM_TYPE . MATCH_LOG ] , catalogers = [ ] , dateBefore = new Date ( ) , dateAfter = '2000-01-01' , test = false } ) {
123
165
logger . debug ( `commons: logItemTypes: ${ JSON . stringify ( logItemTypes ) } , dateAfter: ${ dateAfter } , dateBefore: ${ dateBefore } }, catalogers: ${ JSON . stringify ( catalogers ) } ` ) ;
124
- logger . debug ( JSON . stringify ( generateMatchObject ( logItemTypes , catalogers , dateBefore , dateAfter ) ) ) ; // eslint-disable-line
166
+ logger . debug ( JSON . stringify ( generateMatchObject ( { logItemTypes, catalogers, dateBefore, dateAfter} ) ) ) ; // eslint-disable-line
125
167
//checkLogItemType(logItemType, false, false);
126
168
logger . debug ( `Getting expanded list of logs` ) ;
127
169
const pipeline = [
128
170
// currently return only MERGE_LOG and MATCH_LOG
129
- generateMatchObject ( logItemTypes , catalogers , dateBefore , dateAfter ) ,
171
+ generateMatchObject ( { logItemTypes, catalogers, dateBefore, dateAfter, test } ) ,
130
172
{
131
173
'$sort' :
132
174
{ 'correlationId' : 1 , 'logItemType' : 1 , 'creationTime' : 1 }
@@ -160,18 +202,25 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
160
202
logger . silly ( `Query result: ${ JSON . stringify ( fixedResult ) } ` ) ;
161
203
162
204
logger . debug ( `Query result: ${ fixedResult . length > 0 ? `Found ${ fixedResult . length } log items!` : 'Not found!' } ` ) ;
163
- return { status : fixedResult . length > 0 ? httpStatus . OK : httpStatus . NOT_FOUND , payload : fixedResult . length > 0 ? fixedResult : 'No logs found' } ;
205
+ return fixedResult ;
164
206
165
- function generateMatchObject ( logItemTypes , catalogers , dateBefore , dateAfter ) {
166
- const dateBeforeIso = new Date ( dateBefore ) . toISOString ( ) ;
167
- const dateAfterIso = new Date ( dateAfter ) . toISOString ( ) ;
207
+ /**
208
+ * Generate match object for aggregation pipeline
209
+ * @param {[String] } logItemTypes: String array of logItemTypes.
210
+ * @param {[String] } catalogers: String array of wanted catalogers
211
+ * @param {String } dateBefore: String date schema 'YYYY-MM-DD'
212
+ * @param {String } dateAfter: String date schema 'YYYY-MM-DD'
213
+ * @param {Boolean } test: Boolean is this test run. Defaults false
214
+ * @returns Match Object
215
+ */
216
+ function generateMatchObject ( { logItemTypes, catalogers, dateBefore, dateAfter, test = false } ) {
168
217
const matchOptions = {
169
218
'$match' : {
170
219
'logItemType' : logItemTypes . length > 0 ? { '$in' : logItemTypes } : / .* / ui,
171
220
'cataloger' : catalogers . length > 0 ? { '$in' : catalogers } : / .* / ui,
172
221
'creationTime' : {
173
- '$gte' : dateAfterIso ,
174
- '$lte' : dateBeforeIso
222
+ '$gte' : test ? new Date ( dateAfter ) . toISOString ( ) : new Date ( dateAfter ) ,
223
+ '$lte' : test ? new Date ( dateBefore ) . toISOString ( ) : new Date ( dateBefore )
175
224
}
176
225
}
177
226
} ;
@@ -180,6 +229,12 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
180
229
}
181
230
}
182
231
232
+ /**
233
+ * Protect logs from cleaning. Forced cleaning defaults 30days
234
+ * @param {String } correlationId
235
+ * @param {Integer } blobSequence
236
+ * @returns result
237
+ */
183
238
async function protect ( correlationId , blobSequence ) {
184
239
logger . info ( `Protecting in Mongo (${ collection } ) correlationId: ${ correlationId } , blobSequence: ${ blobSequence } ` ) ;
185
240
const cleanCorrelationId = sanitize ( correlationId ) ;
@@ -198,29 +253,42 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
198
253
}
199
254
]
200
255
) ;
201
- return { status : result . modifiedCount > 0 ? httpStatus . OK : httpStatus . NOT_FOUND , payload : result . modifiedCount > 0 ? result : 'No logs found' } ;
256
+ return result ;
202
257
} catch ( error ) {
203
258
const errorMessage = error . payload || error . message || '' ;
204
259
logError ( error ) ;
205
260
throw new ApiError ( httpStatus . INTERNAL_SERVER_ERROR , `Mongo errored: ${ errorMessage } ` ) ;
206
261
}
207
262
}
208
263
264
+ /**
265
+ * Remove logs
266
+ * @param {String } correlationId
267
+ * @param {Boolean } force defaults false
268
+ * @returns result
269
+ */
209
270
async function remove ( correlationId , force = false ) {
210
271
logger . info ( `Removing from Mongo (${ collection } ) correlationId: ${ correlationId } ` ) ;
211
272
const clean = sanitize ( correlationId ) ;
212
273
const filter = force ? { correlationId : clean } : { correlationId : clean , protected : { $ne : true } } ;
213
274
214
275
try {
215
276
const result = await db . collection ( collection ) . deleteMany ( filter ) ;
216
- return { status : result . deletedCount > 0 ? httpStatus . OK : httpStatus . NOT_FOUND , payload : result . deletedCount > 0 ? result : 'No logs found' } ;
277
+ return result ;
217
278
} catch ( error ) {
218
279
const errorMessage = error . payload || error . message || '' ;
219
280
logError ( error ) ;
220
281
throw new ApiError ( httpStatus . INTERNAL_SERVER_ERROR , `Mongo errored: ${ errorMessage } ` ) ;
221
282
}
222
283
}
223
284
285
+ /**
286
+ * Remove logs by sequences
287
+ * @param {String } correlationId
288
+ * @param {[Integer] } sequences
289
+ * @param {Boolean } force defaults false
290
+ * @returns result
291
+ */
224
292
async function removeBySequences ( correlationId , sequences = [ ] , force = false ) {
225
293
logger . info ( `Removing from Mongo (${ collection } ) correlationId: ${ correlationId } , sequences: ${ sequences . length } ` ) ;
226
294
const clean = sanitize ( correlationId ) ;
@@ -236,16 +304,22 @@ export default async function (MONGO_URI, dbName = 'rest-api') {
236
304
237
305
try {
238
306
const result = await db . collection ( collection ) . deleteMany ( filter ) ;
239
- return { status : result . deletedCount > 0 ? httpStatus . OK : httpStatus . NOT_FOUND , payload : result . deletedCount > 0 ? result : 'No logs found' } ;
307
+ return result ;
240
308
} catch ( error ) {
241
309
const errorMessage = error . payload || error . message || '' ;
242
310
logError ( error ) ;
243
311
throw new ApiError ( httpStatus . INTERNAL_SERVER_ERROR , `Mongo errored: ${ errorMessage } ` ) ;
244
312
}
245
313
}
246
314
315
+ /**
316
+ * Checks existence and validity of logItemType
317
+ * @param {String } logItemType constant LOG_ITEM_TYPE
318
+ * @param {Boolean } errorUnknown defaults false
319
+ * @param {Boolean } errorNotExisting defaults false
320
+ * @returns void
321
+ */
247
322
function checkLogItemType ( logItemType , errorUnknown = false , errorNotExisting = false ) {
248
-
249
323
if ( logItemType ) {
250
324
const typeInLogItemTypes = Object . values ( LOG_ITEM_TYPE ) . indexOf ( logItemType ) > - 1 ;
251
325
if ( typeInLogItemTypes ) {
0 commit comments