@natlibfi/melinda-rest-api-commons 4.2.5 → 5.0.0-alpha.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.
- package/.github/workflows/melinda-node-tests.yml +9 -6
- package/dist/amqp.js +60 -151
- package/dist/amqp.js.map +7 -1
- package/dist/constants.js +40 -51
- package/dist/constants.js.map +7 -1
- package/dist/helpers/conversion.js +39 -57
- package/dist/helpers/conversion.js.map +7 -1
- package/dist/helpers/fix-constants.js +40 -47
- package/dist/helpers/fix-constants.js.map +7 -1
- package/dist/helpers/fix-handle-tempurns.js +23 -73
- package/dist/helpers/fix-handle-tempurns.js.map +7 -1
- package/dist/helpers/fix-strip-f884s.js +44 -94
- package/dist/helpers/fix-strip-f884s.js.map +7 -1
- package/dist/helpers/fix-utils.js +7 -22
- package/dist/helpers/fix-utils.js.map +7 -1
- package/dist/helpers/fix.js +62 -122
- package/dist/helpers/fix.js.map +7 -1
- package/dist/helpers/validation.js +12 -30
- package/dist/helpers/validation.js.map +7 -1
- package/dist/index.js +10 -109
- package/dist/index.js.map +7 -1
- package/dist/mongo.js +173 -509
- package/dist/mongo.js.map +7 -1
- package/dist/mongoLog.js +92 -317
- package/dist/mongoLog.js.map +7 -1
- package/dist/utils.js +46 -155
- package/dist/utils.js.map +7 -1
- package/eslint.config.js +53 -0
- package/package.json +23 -96
- package/tests/{amqp.health.spec.js → amqp.healthtest.js} +2 -2
- package/tests/{amqp.tests.spec.js → amqp.tests.localtest.js} +46 -46
- package/tests/helpers/{conversion.spec.js → conversion.test.js} +38 -25
- package/tests/helpers/{fix.spec.js → fix.test.js} +6 -6
- package/tests/helpers/{validation.spec.js → validation.test.js} +12 -9
- package/tests/{mongo-add-blob-size.spec.js → mongo-add-blob-size.test.js} +6 -6
- package/tests/{mongo-check-and-check-state.spec.js → mongo-check-and-check-state.test.js} +7 -7
- package/tests/{mongo-check-and-set-import-job-state.spec.js → mongo-check-and-set-import-job-state.test.js} +7 -7
- package/tests/{mongo-check-timeout.spec.js → mongo-check-timeout.test.js} +7 -7
- package/tests/{mongo-create-bulk.spec.js → mongo-create-bulk.test.js} +5 -5
- package/tests/{mongo-create-prio.spec.js → mongo-create-prio.test.js} +6 -6
- package/tests/{mongo-get-one.spec.js → mongo-get-one.test.js} +7 -7
- package/tests/{mongo-get-stream.spec.js → mongo-get-stream.test.js} +7 -7
- package/tests/{mongo-push-ids.spec.js → mongo-push-ids.test.js} +5 -5
- package/tests/{mongo-push-messages.spec.js → mongo-push-messages.test.js} +6 -6
- package/tests/{mongo-query-by-id.spec.js → mongo-query-by-id.test.js} +7 -7
- package/tests/{mongo-query.spec.js → mongo-query.test.js} +7 -7
- package/tests/{mongo-read-content.spec.js → mongo-read-content.test.js} +8 -8
- package/tests/{mongo-remove.spec.js → mongo-remove.test.js} +6 -6
- package/tests/{mongo-set-blob-size.spec.js → mongo-set-blob-size.test.js} +6 -6
- package/tests/{mongo-set-import-job-state.spec.js → mongo-set-import-job-state.test.js} +6 -6
- package/tests/{mongo-set-operation.spec.js → mongo-set-operation.test.js} +6 -6
- package/tests/{mongo-set-operations.spec.js → mongo-set-operations.test.js} +6 -6
- package/tests/{mongo-set-state.spec.js → mongo-set-state.test.js} +7 -7
- package/tests/{mongoLog.spec.js → mongoLog.test.js} +10 -11
- package/tests/testUtils.js +9 -8
|
@@ -11,12 +11,12 @@ jobs:
|
|
|
11
11
|
|
|
12
12
|
strategy:
|
|
13
13
|
matrix:
|
|
14
|
-
node-version: [
|
|
14
|
+
node-version: [22.x, 24.x]
|
|
15
15
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
16
16
|
|
|
17
17
|
steps:
|
|
18
18
|
- name: Checkout the code
|
|
19
|
-
uses: actions/checkout@
|
|
19
|
+
uses: actions/checkout@v5
|
|
20
20
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
21
21
|
uses: actions/setup-node@v4
|
|
22
22
|
with:
|
|
@@ -33,20 +33,22 @@ jobs:
|
|
|
33
33
|
license-scan:
|
|
34
34
|
name: License compliance check
|
|
35
35
|
runs-on: ubuntu-latest
|
|
36
|
+
container: node:22
|
|
36
37
|
|
|
37
38
|
steps:
|
|
38
|
-
- uses: actions/checkout@
|
|
39
|
-
- uses: mikaelvesavuori/license-compliance-action@v1
|
|
39
|
+
- uses: actions/checkout@v5
|
|
40
|
+
- uses: mikaelvesavuori/license-compliance-action@v1
|
|
40
41
|
with:
|
|
41
42
|
exclude_pattern: /^@natlibfi/
|
|
42
43
|
|
|
43
44
|
njsscan:
|
|
44
45
|
name: Njsscan check
|
|
45
46
|
runs-on: ubuntu-latest
|
|
47
|
+
container: node:22
|
|
46
48
|
|
|
47
49
|
steps:
|
|
48
50
|
- name: Checkout the code
|
|
49
|
-
uses: actions/checkout@
|
|
51
|
+
uses: actions/checkout@v5
|
|
50
52
|
- name: nodejsscan scan
|
|
51
53
|
id: njsscan
|
|
52
54
|
uses: ajinabraham/njsscan-action@master
|
|
@@ -57,9 +59,10 @@ jobs:
|
|
|
57
59
|
runs-on: ubuntu-latest
|
|
58
60
|
needs: [build-node-versions, njsscan]
|
|
59
61
|
if: contains(github.ref, 'refs/tags/')
|
|
62
|
+
container: node:22
|
|
60
63
|
|
|
61
64
|
steps:
|
|
62
|
-
- uses: actions/checkout@
|
|
65
|
+
- uses: actions/checkout@v5
|
|
63
66
|
# Setup .npmrc file to publish to npm
|
|
64
67
|
- uses: actions/setup-node@v4
|
|
65
68
|
with:
|
package/dist/amqp.js
CHANGED
|
@@ -1,44 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
var _utils = require("./utils");
|
|
17
|
-
async function _default(AMQP_URL, runHealthCheck = false) {
|
|
18
|
-
const logger = (0, _melindaBackendCommons.createLogger)();
|
|
19
|
-
const debug = (0, _debug.default)('@natlibfi/melinda-rest-api-commons:amqp');
|
|
20
|
-
const debugHC = debug.extend('HC');
|
|
21
|
-
const debugData = debug.extend('data');
|
|
22
|
-
const setTimeoutPromise = (0, _util.promisify)(setTimeout);
|
|
1
|
+
import amqplib from "amqplib";
|
|
2
|
+
import createDebugLogger from "debug";
|
|
3
|
+
import { promisify, inspect } from "util";
|
|
4
|
+
import httpStatus from "http-status";
|
|
5
|
+
import { MarcRecord } from "@natlibfi/marc-record";
|
|
6
|
+
import { Error as ApiError } from "@natlibfi/melinda-commons";
|
|
7
|
+
import { createLogger } from "@natlibfi/melinda-backend-commons";
|
|
8
|
+
import { CHUNK_SIZE } from "./constants.js";
|
|
9
|
+
import { logError } from "./utils.js";
|
|
10
|
+
export default async function(AMQP_URL, runHealthCheck = false) {
|
|
11
|
+
const logger = createLogger();
|
|
12
|
+
const debug = createDebugLogger("@natlibfi/melinda-rest-api-commons:amqp");
|
|
13
|
+
const debugHC = debug.extend("HC");
|
|
14
|
+
const debugData = debug.extend("data");
|
|
15
|
+
const setTimeoutPromise = promisify(setTimeout);
|
|
23
16
|
debug(`Creating an AMQP operator to ${AMQP_URL}`);
|
|
24
|
-
const connection = await
|
|
17
|
+
const connection = await amqplib.connect(AMQP_URL);
|
|
25
18
|
const channel = await connection.createChannel();
|
|
26
19
|
const healthCheckLoop = runHealthCheck ? healthCheck() : false;
|
|
27
20
|
debug(`Connection: ${connection}`);
|
|
28
21
|
debug(`Channel: ${channel}`);
|
|
29
|
-
debug(`HealthCheckLoop: ${healthCheckLoop ?
|
|
30
|
-
return {
|
|
31
|
-
checkQueue,
|
|
32
|
-
consumeChunk,
|
|
33
|
-
consumeOne,
|
|
34
|
-
ackMessages,
|
|
35
|
-
nackMessages,
|
|
36
|
-
sendToQueue,
|
|
37
|
-
removeQueue,
|
|
38
|
-
messagesToRecords,
|
|
39
|
-
closeChannel,
|
|
40
|
-
closeConnection
|
|
41
|
-
};
|
|
22
|
+
debug(`HealthCheckLoop: ${healthCheckLoop ? "Running health check" : "Not running health check"}`);
|
|
23
|
+
return { checkQueue, consumeChunk, consumeOne, ackMessages, nackMessages, sendToQueue, removeQueue, messagesToRecords, closeChannel, closeConnection };
|
|
42
24
|
async function closeChannel() {
|
|
43
25
|
debug(`Closing channel`);
|
|
44
26
|
await channel.close();
|
|
@@ -56,9 +38,7 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
56
38
|
}
|
|
57
39
|
try {
|
|
58
40
|
debugHC(`Health checking amqp by asserting a queue`);
|
|
59
|
-
await channel.assertQueue(
|
|
60
|
-
durable: false
|
|
61
|
-
});
|
|
41
|
+
await channel.assertQueue("HEALTHCHECK", { durable: false });
|
|
62
42
|
debugHC(`Waiting 200ms before running healthCheck next`);
|
|
63
43
|
return healthCheck(200);
|
|
64
44
|
} catch (error) {
|
|
@@ -66,55 +46,33 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
66
46
|
handleAmqpErrors(error);
|
|
67
47
|
}
|
|
68
48
|
}
|
|
69
|
-
|
|
70
|
-
// eslint-disable-next-line max-statements
|
|
71
|
-
async function checkQueue({
|
|
72
|
-
queue,
|
|
73
|
-
style = 'basic',
|
|
74
|
-
toRecord = true,
|
|
75
|
-
purge = false
|
|
76
|
-
}) {
|
|
49
|
+
async function checkQueue({ queue, style = "basic", toRecord = true, purge = false }) {
|
|
77
50
|
debug(`checkQueue: ${queue}, Style: ${style}, toRecord: ${toRecord}, Purge: ${purge}`);
|
|
78
51
|
try {
|
|
79
52
|
errorUndefinedQueue(queue);
|
|
80
|
-
const channelInfo = await channel.assertQueue(queue, {
|
|
81
|
-
durable: true
|
|
82
|
-
});
|
|
53
|
+
const channelInfo = await channel.assertQueue(queue, { durable: true });
|
|
83
54
|
if (purge) {
|
|
84
55
|
await purgeQueue(purge);
|
|
85
56
|
logger.verbose(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);
|
|
86
57
|
debug(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);
|
|
87
|
-
return checkQueue({
|
|
88
|
-
queue,
|
|
89
|
-
style
|
|
90
|
-
});
|
|
58
|
+
return checkQueue({ queue, style });
|
|
91
59
|
}
|
|
92
|
-
if (style ===
|
|
60
|
+
if (style === "messages") {
|
|
93
61
|
return channelInfo.messageCount;
|
|
94
62
|
}
|
|
95
|
-
|
|
96
|
-
// Note: returns one message (+ record, of toRecord: true)
|
|
97
|
-
// note: if toRecord is false returns just plain message / false
|
|
98
|
-
// note: if toRecord is true returns {headers, records, messages} -object / false
|
|
99
|
-
// should this be more consistent?
|
|
100
|
-
if (style === 'one') {
|
|
63
|
+
if (style === "one") {
|
|
101
64
|
if (checkMessageCount(channelInfo)) {
|
|
102
65
|
return consumeOne(queue, toRecord);
|
|
103
66
|
}
|
|
104
67
|
return false;
|
|
105
68
|
}
|
|
106
|
-
|
|
107
|
-
// Note: returns a chunk of (100) messages (+ records, if toRecord: true)
|
|
108
|
-
// returns {headers, records, messages} object or {headers, messages} object depending on toRecord
|
|
109
|
-
if (style === 'basic') {
|
|
69
|
+
if (style === "basic") {
|
|
110
70
|
if (checkMessageCount(channelInfo)) {
|
|
111
71
|
return consumeChunk(queue, toRecord);
|
|
112
72
|
}
|
|
113
73
|
return false;
|
|
114
74
|
}
|
|
115
|
-
|
|
116
|
-
// Defaults:
|
|
117
|
-
throw new _melindaCommons.Error(_httpStatus.default.INTERNAL_SERVER_ERROR, `CheckQueue does not recognize style ${style}`);
|
|
75
|
+
throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `CheckQueue does not recognize style ${style}`);
|
|
118
76
|
} catch (error) {
|
|
119
77
|
handleAmqpErrors(error);
|
|
120
78
|
}
|
|
@@ -126,9 +84,9 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
126
84
|
debug(`Queue ${queue} has ${channelInfo.messageCount} messages`);
|
|
127
85
|
return true;
|
|
128
86
|
}
|
|
129
|
-
function purgeQueue(
|
|
130
|
-
debug(`Purging queue: ${queue}, purge: ${
|
|
131
|
-
if (
|
|
87
|
+
function purgeQueue(purge2) {
|
|
88
|
+
debug(`Purging queue: ${queue}, purge: ${purge2}`);
|
|
89
|
+
if (purge2) {
|
|
132
90
|
return channel.purgeQueue(queue);
|
|
133
91
|
}
|
|
134
92
|
}
|
|
@@ -136,28 +94,15 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
136
94
|
async function consumeChunk(queue, toRecord) {
|
|
137
95
|
debug(`Prepared to consumeChunk from queue: ${queue}`);
|
|
138
96
|
try {
|
|
139
|
-
await channel.assertQueue(queue, {
|
|
140
|
-
durable: true
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// getData: next chunk (100) messages
|
|
97
|
+
await channel.assertQueue(queue, { durable: true });
|
|
144
98
|
const messages = await getData(queue);
|
|
145
|
-
|
|
146
|
-
// Note: headers are from the first message of the chunk
|
|
147
99
|
const headers = getHeaderInfo(messages[0]);
|
|
148
|
-
debug(`consumeChunk (${messages ? messages.length :
|
|
100
|
+
debug(`consumeChunk (${messages ? messages.length : "0"} from queue ${queue}) ${toRecord ? "to records" : "just messages"}`);
|
|
149
101
|
if (toRecord) {
|
|
150
102
|
const records = await messagesToRecords(messages);
|
|
151
|
-
return {
|
|
152
|
-
headers,
|
|
153
|
-
records,
|
|
154
|
-
messages
|
|
155
|
-
};
|
|
103
|
+
return { headers, records, messages };
|
|
156
104
|
}
|
|
157
|
-
return {
|
|
158
|
-
headers,
|
|
159
|
-
messages
|
|
160
|
-
};
|
|
105
|
+
return { headers, messages };
|
|
161
106
|
} catch (error) {
|
|
162
107
|
handleAmqpErrors(error);
|
|
163
108
|
}
|
|
@@ -165,28 +110,15 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
165
110
|
async function consumeOne(queue, toRecord) {
|
|
166
111
|
debug(`Prepared to consumeOne from queue: ${queue}`);
|
|
167
112
|
try {
|
|
168
|
-
await channel.assertQueue(queue, {
|
|
169
|
-
durable: true
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Returns false if 0 items in queue
|
|
113
|
+
await channel.assertQueue(queue, { durable: true });
|
|
173
114
|
const message = await channel.get(queue);
|
|
174
|
-
debugData(`Message: ${
|
|
175
|
-
|
|
176
|
-
maxArrayLength: 3,
|
|
177
|
-
depth: 3
|
|
178
|
-
})}`);
|
|
179
|
-
// Do not spam the logs
|
|
180
|
-
debug(`consumeOne from queue: ${queue} ${toRecord ? 'to records' : 'just the message'}`);
|
|
115
|
+
debugData(`Message: ${inspect(message, { colors: true, maxArrayLength: 3, depth: 3 })}`);
|
|
116
|
+
debug(`consumeOne from queue: ${queue} ${toRecord ? "to records" : "just the message"}`);
|
|
181
117
|
if (message) {
|
|
182
118
|
if (toRecord) {
|
|
183
119
|
const headers = getHeaderInfo(message);
|
|
184
120
|
const records = messagesToRecords([message]);
|
|
185
|
-
return {
|
|
186
|
-
headers,
|
|
187
|
-
records,
|
|
188
|
-
messages: [message]
|
|
189
|
-
};
|
|
121
|
+
return { headers, records, messages: [message] };
|
|
190
122
|
}
|
|
191
123
|
return message;
|
|
192
124
|
}
|
|
@@ -196,25 +128,19 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
196
128
|
}
|
|
197
129
|
}
|
|
198
130
|
function ackMessages(messages) {
|
|
199
|
-
messages.forEach(message => {
|
|
131
|
+
messages.forEach((message) => {
|
|
200
132
|
debug(`Ack message ${message.properties.correlationId}`);
|
|
201
133
|
channel.ack(message);
|
|
202
134
|
});
|
|
203
135
|
}
|
|
204
136
|
function nackMessages(messages) {
|
|
205
|
-
messages.forEach(message => {
|
|
137
|
+
messages.forEach((message) => {
|
|
206
138
|
debug(`Nack message ${message.properties.correlationId}`);
|
|
207
139
|
channel.nack(message);
|
|
208
140
|
});
|
|
209
141
|
}
|
|
210
|
-
async function sendToQueue({
|
|
211
|
-
queue,
|
|
212
|
-
correlationId,
|
|
213
|
-
headers,
|
|
214
|
-
data
|
|
215
|
-
}) {
|
|
142
|
+
async function sendToQueue({ queue, correlationId, headers, data }) {
|
|
216
143
|
debug(`sendToQueue`);
|
|
217
|
-
// eslint-disable-next-line no-useless-catch
|
|
218
144
|
try {
|
|
219
145
|
debug(`Queue ${queue}`);
|
|
220
146
|
debug(`CorrelationId ${correlationId}`);
|
|
@@ -222,31 +148,25 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
222
148
|
debug(`Headers ${JSON.stringify(headers)}`);
|
|
223
149
|
errorUndefinedQueue(queue);
|
|
224
150
|
debug(`Asserting queue: ${queue}`);
|
|
225
|
-
await channel.assertQueue(queue, {
|
|
226
|
-
durable: true
|
|
227
|
-
});
|
|
151
|
+
await channel.assertQueue(queue, { durable: true });
|
|
228
152
|
debug(`Actually sendToQueue: ${queue}`);
|
|
229
|
-
await channel.sendToQueue(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
153
|
+
await channel.sendToQueue(
|
|
154
|
+
queue,
|
|
155
|
+
Buffer.from(JSON.stringify({ data })),
|
|
156
|
+
{
|
|
157
|
+
correlationId,
|
|
158
|
+
persistent: true,
|
|
159
|
+
headers
|
|
160
|
+
}
|
|
161
|
+
);
|
|
236
162
|
debug(`Send message for ${correlationId} to queue: ${queue}`);
|
|
237
163
|
} catch (error) {
|
|
238
164
|
const errorToThrow = error;
|
|
239
|
-
//if (error instanceof ApiError) {
|
|
240
|
-
// throw error;
|
|
241
|
-
//}
|
|
242
165
|
debug(`SendToQueue errored: ${JSON.stringify(error)}`);
|
|
243
166
|
handleAmqpErrors(errorToThrow);
|
|
244
167
|
}
|
|
245
168
|
}
|
|
246
169
|
async function removeQueue(queue) {
|
|
247
|
-
// deleteQueue borks the channel if the queue does not exist
|
|
248
|
-
// -> use throwaway tempChannel to avoid killing actual channel in use
|
|
249
|
-
// this might be doable also with assertQueue before deleteQueue
|
|
250
170
|
const tempChannel = await connection.createChannel();
|
|
251
171
|
logger.verbose(`Removing queue ${queue}.`);
|
|
252
172
|
debug(`Removing queue ${queue}.`);
|
|
@@ -257,29 +177,19 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
257
177
|
}
|
|
258
178
|
return;
|
|
259
179
|
}
|
|
260
|
-
|
|
261
|
-
// ----------------
|
|
262
|
-
// Helper functions
|
|
263
|
-
// ----------------
|
|
264
|
-
|
|
265
180
|
function messagesToRecords(messages) {
|
|
266
181
|
debug(`Parsing messages (${messages.length}) to records`);
|
|
267
|
-
return messages.map(message => {
|
|
182
|
+
return messages.map((message) => {
|
|
268
183
|
const content = JSON.parse(message.content.toString());
|
|
269
|
-
|
|
270
|
-
return new _marcRecord.MarcRecord(content.data, {
|
|
271
|
-
subfieldValues: false
|
|
272
|
-
});
|
|
184
|
+
return new MarcRecord(content.data, { subfieldValues: false });
|
|
273
185
|
});
|
|
274
186
|
}
|
|
275
187
|
async function getData(queue) {
|
|
276
188
|
debug(`Getting queue data from ${queue}`);
|
|
277
189
|
try {
|
|
278
|
-
const {
|
|
279
|
-
messageCount
|
|
280
|
-
} = await channel.checkQueue(queue);
|
|
190
|
+
const { messageCount } = await channel.checkQueue(queue);
|
|
281
191
|
debug(`There is ${messageCount} messages in queue ${queue}`);
|
|
282
|
-
const messagesToGet = messageCount >=
|
|
192
|
+
const messagesToGet = messageCount >= CHUNK_SIZE ? CHUNK_SIZE : messageCount;
|
|
283
193
|
debug(`Getting ${messagesToGet} messages from queue ${queue}`);
|
|
284
194
|
const messages = await pump(messagesToGet);
|
|
285
195
|
debug(`Returning ${messages.length} unique messages`);
|
|
@@ -296,7 +206,6 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
296
206
|
correlationId: message.properties.correlationId,
|
|
297
207
|
deliveryTag: message.fields.deliveryTag
|
|
298
208
|
};
|
|
299
|
-
// Filter not unique messages
|
|
300
209
|
if (identifiers.includes(identifier)) {
|
|
301
210
|
return pump(count - 1, results, identifiers);
|
|
302
211
|
}
|
|
@@ -307,20 +216,20 @@ async function _default(AMQP_URL, runHealthCheck = false) {
|
|
|
307
216
|
return data.properties.headers;
|
|
308
217
|
}
|
|
309
218
|
function errorUndefinedQueue(queue) {
|
|
310
|
-
if (queue ===
|
|
311
|
-
throw new
|
|
219
|
+
if (queue === void 0 || queue === "" || queue === null) {
|
|
220
|
+
throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `Undefined queue!`);
|
|
312
221
|
}
|
|
313
222
|
}
|
|
314
223
|
function handleAmqpErrors(error) {
|
|
315
224
|
const newError = error;
|
|
316
225
|
debug(`HandleAmqpErrors got an error: ${JSON.stringify(error)}`);
|
|
317
|
-
if (error instanceof
|
|
226
|
+
if (error instanceof ApiError) {
|
|
318
227
|
debug(`We have an ApiError`);
|
|
319
|
-
throw new
|
|
228
|
+
throw new ApiError(newError.status, newError.payload);
|
|
320
229
|
}
|
|
321
230
|
debug(`We have a non-ApiError`);
|
|
322
|
-
|
|
231
|
+
logError(error);
|
|
323
232
|
throw newError;
|
|
324
233
|
}
|
|
325
234
|
}
|
|
326
|
-
//# sourceMappingURL=amqp.js.map
|
|
235
|
+
//# sourceMappingURL=amqp.js.map
|
package/dist/amqp.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{"version":3,"file":"amqp.js","names":["_amqplib","_interopRequireDefault","require","_marcRecord","_melindaCommons","_melindaBackendCommons","_debug","_constants","_util","_httpStatus","_utils","_default","AMQP_URL","runHealthCheck","logger","createLogger","debug","createDebugLogger","debugHC","extend","debugData","setTimeoutPromise","promisify","setTimeout","connection","amqplib","connect","channel","createChannel","healthCheckLoop","healthCheck","checkQueue","consumeChunk","consumeOne","ackMessages","nackMessages","sendToQueue","removeQueue","messagesToRecords","closeChannel","closeConnection","close","wait","assertQueue","durable","error","JSON","stringify","handleAmqpErrors","queue","style","toRecord","purge","errorUndefinedQueue","channelInfo","purgeQueue","verbose","messageCount","checkMessageCount","ApiError","httpStatus","INTERNAL_SERVER_ERROR","messages","getData","headers","getHeaderInfo","length","records","message","get","inspect","colors","maxArrayLength","depth","forEach","properties","correlationId","ack","nack","data","Buffer","from","persistent","errorToThrow","tempChannel","deleteQueue","map","content","parse","toString","MarcRecord","subfieldValues","messagesToGet","CHUNK_SIZE","pump","count","results","identifiers","identifier","deliveryTag","fields","includes","concat","undefined","newError","status","payload","logError"],"sources":["../src/amqp.js"],"sourcesContent":["import amqplib from 'amqplib';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {Error as ApiError} from '@natlibfi/melinda-commons';\nimport {createLogger} from '@natlibfi/melinda-backend-commons';\nimport createDebugLogger from 'debug';\nimport {CHUNK_SIZE} from './constants';\nimport {promisify, inspect} from 'util';\nimport httpStatus from 'http-status';\nimport {logError} from './utils';\n\nexport default async function (AMQP_URL, runHealthCheck = false) {\n const logger = createLogger();\n const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:amqp');\n const debugHC = debug.extend('HC');\n const debugData = debug.extend('data');\n const setTimeoutPromise = promisify(setTimeout);\n\n debug(`Creating an AMQP operator to ${AMQP_URL}`);\n const connection = await amqplib.connect(AMQP_URL);\n const channel = await connection.createChannel();\n\n const healthCheckLoop = runHealthCheck ? healthCheck() : false;\n\n debug(`Connection: ${connection}`);\n debug(`Channel: ${channel}`);\n debug(`HealthCheckLoop: ${healthCheckLoop ? 'Running health check' : 'Not running health check'}`);\n\n return {checkQueue, consumeChunk, consumeOne, ackMessages, nackMessages, sendToQueue, removeQueue, messagesToRecords, closeChannel, closeConnection};\n\n async function closeChannel() {\n debug(`Closing channel`);\n await channel.close();\n debug(`Channel: ${channel}`);\n }\n\n async function closeConnection() {\n debug(`Closing connection`);\n await connection.close();\n debug(`Connection: ${connection}`);\n }\n\n async function healthCheck(wait = false) {\n if (wait) {\n await setTimeoutPromise(wait);\n return healthCheck(false);\n }\n\n try {\n debugHC(`Health checking amqp by asserting a queue`);\n await channel.assertQueue('HEALTHCHECK', {durable: false});\n debugHC(`Waiting 200ms before running healthCheck next`);\n return healthCheck(200);\n } catch (error) {\n debugHC(`HealthCheck error ${JSON.stringify(error)}`);\n handleAmqpErrors(error);\n }\n }\n\n // eslint-disable-next-line max-statements\n async function checkQueue({queue, style = 'basic', toRecord = true, purge = false}) {\n debug(`checkQueue: ${queue}, Style: ${style}, toRecord: ${toRecord}, Purge: ${purge}`);\n\n try {\n\n errorUndefinedQueue(queue);\n const channelInfo = await channel.assertQueue(queue, {durable: true});\n\n if (purge) {\n await purgeQueue(purge);\n logger.verbose(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);\n debug(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);\n return checkQueue({queue, style});\n }\n\n if (style === 'messages') {\n return channelInfo.messageCount;\n }\n\n\n // Note: returns one message (+ record, of toRecord: true)\n // note: if toRecord is false returns just plain message / false\n // note: if toRecord is true returns {headers, records, messages} -object / false\n // should this be more consistent?\n if (style === 'one') {\n if (checkMessageCount(channelInfo)) {\n return consumeOne(queue, toRecord);\n }\n return false;\n }\n\n // Note: returns a chunk of (100) messages (+ records, if toRecord: true)\n // returns {headers, records, messages} object or {headers, messages} object depending on toRecord\n if (style === 'basic') {\n if (checkMessageCount(channelInfo)) {\n return consumeChunk(queue, toRecord);\n }\n return false;\n }\n\n // Defaults:\n throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `CheckQueue does not recognize style ${style}`);\n } catch (error) {\n handleAmqpErrors(error);\n }\n\n function checkMessageCount(channelInfo) {\n if (channelInfo.messageCount < 1) {\n debug(`checkQueue: ${channelInfo.messageCount} - ${queue} is empty`);\n return false;\n }\n debug(`Queue ${queue} has ${channelInfo.messageCount} messages`);\n return true;\n }\n\n function purgeQueue(purge) {\n debug(`Purging queue: ${queue}, purge: ${purge}`);\n if (purge) {\n return channel.purgeQueue(queue);\n }\n }\n }\n\n async function consumeChunk(queue, toRecord) {\n debug(`Prepared to consumeChunk from queue: ${queue}`);\n try {\n await channel.assertQueue(queue, {durable: true});\n\n // getData: next chunk (100) messages\n const messages = await getData(queue);\n\n // Note: headers are from the first message of the chunk\n const headers = getHeaderInfo(messages[0]);\n debug(`consumeChunk (${messages ? messages.length : '0'} from queue ${queue}) ${toRecord ? 'to records' : 'just messages'}`);\n\n if (toRecord) {\n const records = await messagesToRecords(messages);\n return {headers, records, messages};\n }\n\n return {headers, messages};\n } catch (error) {\n handleAmqpErrors(error);\n }\n }\n\n async function consumeOne(queue, toRecord) {\n debug(`Prepared to consumeOne from queue: ${queue}`);\n try {\n await channel.assertQueue(queue, {durable: true});\n\n // Returns false if 0 items in queue\n const message = await channel.get(queue);\n\n debugData(`Message: ${inspect(message, {colors: true, maxArrayLength: 3, depth: 3})}`);\n // Do not spam the logs\n debug(`consumeOne from queue: ${queue} ${toRecord ? 'to records' : 'just the message'}`);\n\n if (message) {\n if (toRecord) {\n const headers = getHeaderInfo(message);\n const records = messagesToRecords([message]);\n return {headers, records, messages: [message]};\n }\n\n return message;\n }\n\n return false;\n } catch (error) {\n handleAmqpErrors(error);\n }\n }\n\n function ackMessages(messages) {\n messages.forEach(message => {\n debug(`Ack message ${message.properties.correlationId}`);\n channel.ack(message);\n });\n }\n\n function nackMessages(messages) {\n messages.forEach(message => {\n debug(`Nack message ${message.properties.correlationId}`);\n channel.nack(message);\n });\n }\n\n async function sendToQueue({queue, correlationId, headers, data}) {\n debug(`sendToQueue`);\n // eslint-disable-next-line no-useless-catch\n try {\n debug(`Queue ${queue}`);\n debug(`CorrelationId ${correlationId}`);\n debugData(`Data ${JSON.stringify(data)}`);\n debug(`Headers ${JSON.stringify(headers)}`);\n\n errorUndefinedQueue(queue);\n\n debug(`Asserting queue: ${queue}`);\n await channel.assertQueue(queue, {durable: true});\n\n debug(`Actually sendToQueue: ${queue}`);\n await channel.sendToQueue(\n queue,\n Buffer.from(JSON.stringify({data})),\n {\n correlationId,\n persistent: true,\n headers\n }\n );\n debug(`Send message for ${correlationId} to queue: ${queue}`);\n\n\n } catch (error) {\n const errorToThrow = error;\n //if (error instanceof ApiError) {\n // throw error;\n //}\n debug(`SendToQueue errored: ${JSON.stringify(error)}`);\n handleAmqpErrors(errorToThrow);\n }\n }\n\n async function removeQueue(queue) {\n // deleteQueue borks the channel if the queue does not exist\n // -> use throwaway tempChannel to avoid killing actual channel in use\n // this might be doable also with assertQueue before deleteQueue\n const tempChannel = await connection.createChannel();\n logger.verbose(`Removing queue ${queue}.`);\n debug(`Removing queue ${queue}.`);\n await tempChannel.deleteQueue(queue);\n\n if (tempChannel) {\n await tempChannel.close();\n return;\n }\n\n return;\n }\n\n // ----------------\n // Helper functions\n // ----------------\n\n function messagesToRecords(messages) {\n debug(`Parsing messages (${messages.length}) to records`);\n\n return messages.map(message => {\n const content = JSON.parse(message.content.toString());\n // Use subfieldValues: false validationOption here\n return new MarcRecord(content.data, {subfieldValues: false});\n });\n }\n\n async function getData(queue) {\n debug(`Getting queue data from ${queue}`);\n try {\n const {messageCount} = await channel.checkQueue(queue);\n debug(`There is ${messageCount} messages in queue ${queue}`);\n const messagesToGet = messageCount >= CHUNK_SIZE ? CHUNK_SIZE : messageCount;\n debug(`Getting ${messagesToGet} messages from queue ${queue}`);\n\n const messages = await pump(messagesToGet);\n\n debug(`Returning ${messages.length} unique messages`);\n\n return messages;\n } catch (error) {\n handleAmqpErrors(error);\n }\n\n async function pump(count, results = [], identifiers = []) {\n if (count === 0) {\n return results;\n }\n\n const message = await channel.get(queue);\n const identifier = {\n correlationId: message.properties.correlationId,\n deliveryTag: message.fields.deliveryTag\n };\n // Filter not unique messages\n if (identifiers.includes(identifier)) {\n return pump(count - 1, results, identifiers);\n }\n\n return pump(count - 1, results.concat(message), identifiers.concat(identifier));\n }\n }\n\n function getHeaderInfo(data) {\n return data.properties.headers;\n }\n\n function errorUndefinedQueue(queue) {\n if (queue === undefined || queue === '' || queue === null) {\n throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `Undefined queue!`);\n }\n }\n\n function handleAmqpErrors(error) {\n const newError = error;\n debug(`HandleAmqpErrors got an error: ${JSON.stringify(error)}`);\n if (error instanceof ApiError) {\n debug(`We have an ApiError`);\n throw new ApiError(newError.status, newError.payload);\n }\n debug(`We have a non-ApiError`);\n logError(error);\n throw newError;\n }\n}\n\n\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/amqp.js"],
|
|
4
|
+
"sourcesContent": ["import amqplib from 'amqplib';\nimport createDebugLogger from 'debug';\nimport {promisify, inspect} from 'util';\nimport httpStatus from 'http-status';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {Error as ApiError} from '@natlibfi/melinda-commons';\nimport {createLogger} from '@natlibfi/melinda-backend-commons';\nimport {CHUNK_SIZE} from './constants.js';\nimport {logError} from './utils.js';\n\nexport default async function (AMQP_URL, runHealthCheck = false) {\n const logger = createLogger();\n const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:amqp');\n const debugHC = debug.extend('HC');\n const debugData = debug.extend('data');\n const setTimeoutPromise = promisify(setTimeout);\n\n debug(`Creating an AMQP operator to ${AMQP_URL}`);\n const connection = await amqplib.connect(AMQP_URL);\n const channel = await connection.createChannel();\n\n const healthCheckLoop = runHealthCheck ? healthCheck() : false;\n\n debug(`Connection: ${connection}`);\n debug(`Channel: ${channel}`);\n debug(`HealthCheckLoop: ${healthCheckLoop ? 'Running health check' : 'Not running health check'}`);\n\n return {checkQueue, consumeChunk, consumeOne, ackMessages, nackMessages, sendToQueue, removeQueue, messagesToRecords, closeChannel, closeConnection};\n\n async function closeChannel() {\n debug(`Closing channel`);\n await channel.close();\n debug(`Channel: ${channel}`);\n }\n\n async function closeConnection() {\n debug(`Closing connection`);\n await connection.close();\n debug(`Connection: ${connection}`);\n }\n\n async function healthCheck(wait = false) {\n if (wait) {\n await setTimeoutPromise(wait);\n return healthCheck(false);\n }\n\n try {\n debugHC(`Health checking amqp by asserting a queue`);\n await channel.assertQueue('HEALTHCHECK', {durable: false});\n debugHC(`Waiting 200ms before running healthCheck next`);\n return healthCheck(200);\n } catch (error) {\n debugHC(`HealthCheck error ${JSON.stringify(error)}`);\n handleAmqpErrors(error);\n }\n }\n\n // eslint-disable-next-line max-statements\n async function checkQueue({queue, style = 'basic', toRecord = true, purge = false}) {\n debug(`checkQueue: ${queue}, Style: ${style}, toRecord: ${toRecord}, Purge: ${purge}`);\n\n try {\n\n errorUndefinedQueue(queue);\n const channelInfo = await channel.assertQueue(queue, {durable: true});\n\n if (purge) {\n await purgeQueue(purge);\n logger.verbose(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);\n debug(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);\n return checkQueue({queue, style});\n }\n\n if (style === 'messages') {\n return channelInfo.messageCount;\n }\n\n\n // Note: returns one message (+ record, of toRecord: true)\n // note: if toRecord is false returns just plain message / false\n // note: if toRecord is true returns {headers, records, messages} -object / false\n // should this be more consistent?\n if (style === 'one') {\n if (checkMessageCount(channelInfo)) {\n return consumeOne(queue, toRecord);\n }\n return false;\n }\n\n // Note: returns a chunk of (100) messages (+ records, if toRecord: true)\n // returns {headers, records, messages} object or {headers, messages} object depending on toRecord\n if (style === 'basic') {\n if (checkMessageCount(channelInfo)) {\n return consumeChunk(queue, toRecord);\n }\n return false;\n }\n\n // Defaults:\n throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `CheckQueue does not recognize style ${style}`);\n } catch (error) {\n handleAmqpErrors(error);\n }\n\n function checkMessageCount(channelInfo) {\n if (channelInfo.messageCount < 1) {\n debug(`checkQueue: ${channelInfo.messageCount} - ${queue} is empty`);\n return false;\n }\n debug(`Queue ${queue} has ${channelInfo.messageCount} messages`);\n return true;\n }\n\n function purgeQueue(purge) {\n debug(`Purging queue: ${queue}, purge: ${purge}`);\n if (purge) {\n return channel.purgeQueue(queue);\n }\n }\n }\n\n async function consumeChunk(queue, toRecord) {\n debug(`Prepared to consumeChunk from queue: ${queue}`);\n try {\n await channel.assertQueue(queue, {durable: true});\n\n // getData: next chunk (100) messages\n const messages = await getData(queue);\n\n // Note: headers are from the first message of the chunk\n const headers = getHeaderInfo(messages[0]);\n debug(`consumeChunk (${messages ? messages.length : '0'} from queue ${queue}) ${toRecord ? 'to records' : 'just messages'}`);\n\n if (toRecord) {\n const records = await messagesToRecords(messages);\n return {headers, records, messages};\n }\n\n return {headers, messages};\n } catch (error) {\n handleAmqpErrors(error);\n }\n }\n\n async function consumeOne(queue, toRecord) {\n debug(`Prepared to consumeOne from queue: ${queue}`);\n try {\n await channel.assertQueue(queue, {durable: true});\n\n // Returns false if 0 items in queue\n const message = await channel.get(queue);\n\n debugData(`Message: ${inspect(message, {colors: true, maxArrayLength: 3, depth: 3})}`);\n // Do not spam the logs\n debug(`consumeOne from queue: ${queue} ${toRecord ? 'to records' : 'just the message'}`);\n\n if (message) {\n if (toRecord) {\n const headers = getHeaderInfo(message);\n const records = messagesToRecords([message]);\n return {headers, records, messages: [message]};\n }\n\n return message;\n }\n\n return false;\n } catch (error) {\n handleAmqpErrors(error);\n }\n }\n\n function ackMessages(messages) {\n messages.forEach(message => {\n debug(`Ack message ${message.properties.correlationId}`);\n channel.ack(message);\n });\n }\n\n function nackMessages(messages) {\n messages.forEach(message => {\n debug(`Nack message ${message.properties.correlationId}`);\n channel.nack(message);\n });\n }\n\n async function sendToQueue({queue, correlationId, headers, data}) {\n debug(`sendToQueue`);\n // eslint-disable-next-line no-useless-catch\n try {\n debug(`Queue ${queue}`);\n debug(`CorrelationId ${correlationId}`);\n debugData(`Data ${JSON.stringify(data)}`);\n debug(`Headers ${JSON.stringify(headers)}`);\n\n errorUndefinedQueue(queue);\n\n debug(`Asserting queue: ${queue}`);\n await channel.assertQueue(queue, {durable: true});\n\n debug(`Actually sendToQueue: ${queue}`);\n await channel.sendToQueue(\n queue,\n Buffer.from(JSON.stringify({data})),\n {\n correlationId,\n persistent: true,\n headers\n }\n );\n debug(`Send message for ${correlationId} to queue: ${queue}`);\n\n\n } catch (error) {\n const errorToThrow = error;\n //if (error instanceof ApiError) {\n // throw error;\n //}\n debug(`SendToQueue errored: ${JSON.stringify(error)}`);\n handleAmqpErrors(errorToThrow);\n }\n }\n\n async function removeQueue(queue) {\n // deleteQueue borks the channel if the queue does not exist\n // -> use throwaway tempChannel to avoid killing actual channel in use\n // this might be doable also with assertQueue before deleteQueue\n const tempChannel = await connection.createChannel();\n logger.verbose(`Removing queue ${queue}.`);\n debug(`Removing queue ${queue}.`);\n await tempChannel.deleteQueue(queue);\n\n if (tempChannel) {\n await tempChannel.close();\n return;\n }\n\n return;\n }\n\n // ----------------\n // Helper functions\n // ----------------\n\n function messagesToRecords(messages) {\n debug(`Parsing messages (${messages.length}) to records`);\n\n return messages.map(message => {\n const content = JSON.parse(message.content.toString());\n // Use subfieldValues: false validationOption here\n return new MarcRecord(content.data, {subfieldValues: false});\n });\n }\n\n async function getData(queue) {\n debug(`Getting queue data from ${queue}`);\n try {\n const {messageCount} = await channel.checkQueue(queue);\n debug(`There is ${messageCount} messages in queue ${queue}`);\n const messagesToGet = messageCount >= CHUNK_SIZE ? CHUNK_SIZE : messageCount;\n debug(`Getting ${messagesToGet} messages from queue ${queue}`);\n\n const messages = await pump(messagesToGet);\n\n debug(`Returning ${messages.length} unique messages`);\n\n return messages;\n } catch (error) {\n handleAmqpErrors(error);\n }\n\n async function pump(count, results = [], identifiers = []) {\n if (count === 0) {\n return results;\n }\n\n const message = await channel.get(queue);\n const identifier = {\n correlationId: message.properties.correlationId,\n deliveryTag: message.fields.deliveryTag\n };\n // Filter not unique messages\n if (identifiers.includes(identifier)) {\n return pump(count - 1, results, identifiers);\n }\n\n return pump(count - 1, results.concat(message), identifiers.concat(identifier));\n }\n }\n\n function getHeaderInfo(data) {\n return data.properties.headers;\n }\n\n function errorUndefinedQueue(queue) {\n if (queue === undefined || queue === '' || queue === null) {\n throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `Undefined queue!`);\n }\n }\n\n function handleAmqpErrors(error) {\n const newError = error;\n debug(`HandleAmqpErrors got an error: ${JSON.stringify(error)}`);\n if (error instanceof ApiError) {\n debug(`We have an ApiError`);\n throw new ApiError(newError.status, newError.payload);\n }\n debug(`We have a non-ApiError`);\n logError(error);\n throw newError;\n }\n}\n\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["purge"]
|
|
7
|
+
}
|
package/dist/constants.js
CHANGED
|
@@ -1,60 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.QUEUE_ITEM_STATE = exports.OPERATIONS = exports.LOG_ITEM_TYPE = exports.IMPORT_JOB_STATE = exports.CONVERSION_FORMATS = exports.CHUNK_SIZE = void 0;
|
|
7
|
-
// QueueItemState flows: see README.md
|
|
8
|
-
|
|
9
|
-
const QUEUE_ITEM_STATE = exports.QUEUE_ITEM_STATE = {
|
|
1
|
+
export const QUEUE_ITEM_STATE = {
|
|
10
2
|
VALIDATOR: {
|
|
11
|
-
PENDING_QUEUING:
|
|
12
|
-
PENDING_VALIDATION:
|
|
13
|
-
QUEUING_IN_PROGRESS:
|
|
14
|
-
UPLOADING:
|
|
15
|
-
VALIDATING:
|
|
16
|
-
WAITING_FOR_RECORDS:
|
|
3
|
+
PENDING_QUEUING: "PENDING_QUEUING",
|
|
4
|
+
PENDING_VALIDATION: "PENDING_VALIDATION",
|
|
5
|
+
QUEUING_IN_PROGRESS: "QUEUING_IN_PROGRESS",
|
|
6
|
+
UPLOADING: "UPLOADING",
|
|
7
|
+
VALIDATING: "VALIDATING",
|
|
8
|
+
WAITING_FOR_RECORDS: "WAITING_FOR_RECORDS"
|
|
17
9
|
},
|
|
18
10
|
IMPORTER: {
|
|
19
|
-
IMPORTING:
|
|
20
|
-
IN_PROCESS:
|
|
21
|
-
IN_QUEUE:
|
|
11
|
+
IMPORTING: "IMPORTING",
|
|
12
|
+
IN_PROCESS: "IN_PROCESS",
|
|
13
|
+
IN_QUEUE: "IN_QUEUE"
|
|
22
14
|
},
|
|
23
|
-
DONE:
|
|
24
|
-
ERROR:
|
|
25
|
-
ABORT:
|
|
15
|
+
DONE: "DONE",
|
|
16
|
+
ERROR: "ERROR",
|
|
17
|
+
ABORT: "ABORT"
|
|
26
18
|
};
|
|
27
|
-
const IMPORT_JOB_STATE =
|
|
28
|
-
EMPTY:
|
|
29
|
-
QUEUING:
|
|
30
|
-
IN_QUEUE:
|
|
31
|
-
IMPORTING:
|
|
32
|
-
PROCESSING:
|
|
33
|
-
DONE:
|
|
34
|
-
ERROR:
|
|
35
|
-
ABORT:
|
|
19
|
+
export const IMPORT_JOB_STATE = {
|
|
20
|
+
EMPTY: "EMPTY",
|
|
21
|
+
QUEUING: "QUEUING",
|
|
22
|
+
IN_QUEUE: "IN_QUEUE",
|
|
23
|
+
IMPORTING: "IMPORTING",
|
|
24
|
+
PROCESSING: "PROCESSING",
|
|
25
|
+
DONE: "DONE",
|
|
26
|
+
ERROR: "ERROR",
|
|
27
|
+
ABORT: "ABORT"
|
|
36
28
|
};
|
|
37
|
-
const OPERATIONS =
|
|
38
|
-
CREATE:
|
|
39
|
-
UPDATE:
|
|
40
|
-
FIX:
|
|
29
|
+
export const OPERATIONS = {
|
|
30
|
+
CREATE: "CREATE",
|
|
31
|
+
UPDATE: "UPDATE",
|
|
32
|
+
FIX: "FIX"
|
|
41
33
|
};
|
|
42
|
-
const CHUNK_SIZE =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
RESULT_RECORD_LOG: 'RESULT_RECORD_LOG',
|
|
51
|
-
SPLITTER_LOG: 'SPLITTER_LOG',
|
|
52
|
-
LOAD_PROCESS_LOG: 'LOAD_PROCESS_LOG'
|
|
34
|
+
export const CHUNK_SIZE = 100;
|
|
35
|
+
export const LOG_ITEM_TYPE = {
|
|
36
|
+
INPUT_RECORD_LOG: "INPUT_RECORD_LOG",
|
|
37
|
+
MERGE_LOG: "MERGE_LOG",
|
|
38
|
+
MATCH_LOG: "MATCH_LOG",
|
|
39
|
+
RESULT_RECORD_LOG: "RESULT_RECORD_LOG",
|
|
40
|
+
SPLITTER_LOG: "SPLITTER_LOG",
|
|
41
|
+
LOAD_PROCESS_LOG: "LOAD_PROCESS_LOG"
|
|
53
42
|
};
|
|
54
|
-
const CONVERSION_FORMATS =
|
|
55
|
-
MARCXML:
|
|
56
|
-
ISO2709:
|
|
57
|
-
JSON:
|
|
58
|
-
ALEPHSEQ:
|
|
43
|
+
export const CONVERSION_FORMATS = {
|
|
44
|
+
MARCXML: "MARCXML",
|
|
45
|
+
ISO2709: "ISO2709",
|
|
46
|
+
JSON: "JSON",
|
|
47
|
+
ALEPHSEQ: "ALEPHSEQ"
|
|
59
48
|
};
|
|
60
|
-
//# sourceMappingURL=constants.js.map
|
|
49
|
+
//# sourceMappingURL=constants.js.map
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/constants.js"],
|
|
4
|
+
"sourcesContent": ["// QueueItemState flows: see README.md\n\nexport const QUEUE_ITEM_STATE = {\n VALIDATOR: {\n PENDING_QUEUING: 'PENDING_QUEUING',\n PENDING_VALIDATION: 'PENDING_VALIDATION',\n QUEUING_IN_PROGRESS: 'QUEUING_IN_PROGRESS',\n UPLOADING: 'UPLOADING',\n VALIDATING: 'VALIDATING',\n WAITING_FOR_RECORDS: 'WAITING_FOR_RECORDS'\n },\n IMPORTER: {\n IMPORTING: 'IMPORTING',\n IN_PROCESS: 'IN_PROCESS',\n IN_QUEUE: 'IN_QUEUE'\n },\n DONE: 'DONE',\n ERROR: 'ERROR',\n ABORT: 'ABORT'\n};\n\nexport const IMPORT_JOB_STATE = {\n EMPTY: 'EMPTY',\n QUEUING: 'QUEUING',\n IN_QUEUE: 'IN_QUEUE',\n IMPORTING: 'IMPORTING',\n PROCESSING: 'PROCESSING',\n DONE: 'DONE',\n ERROR: 'ERROR',\n ABORT: 'ABORT'\n};\n\nexport const OPERATIONS = {\n CREATE: 'CREATE',\n UPDATE: 'UPDATE',\n FIX: 'FIX'\n};\n\nexport const CHUNK_SIZE = 100;\n\n// We could configure here whether a logItemType is for a several records of a single record\n// ie. whether is has bulkSequence or bulkSequenceStart & bulkSequenceEnd\nexport const LOG_ITEM_TYPE = {\n INPUT_RECORD_LOG: 'INPUT_RECORD_LOG',\n MERGE_LOG: 'MERGE_LOG',\n MATCH_LOG: 'MATCH_LOG',\n RESULT_RECORD_LOG: 'RESULT_RECORD_LOG',\n SPLITTER_LOG: 'SPLITTER_LOG',\n LOAD_PROCESS_LOG: 'LOAD_PROCESS_LOG'\n};\n\nexport const CONVERSION_FORMATS = {\n MARCXML: 'MARCXML',\n ISO2709: 'ISO2709',\n JSON: 'JSON',\n ALEPHSEQ: 'ALEPHSEQ'\n};\n"],
|
|
5
|
+
"mappings": "AAEO,aAAM,mBAAmB;AAAA,EAC9B,WAAW;AAAA,IACT,iBAAiB;AAAA,IACjB,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,IACrB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,qBAAqB;AAAA,EACvB;AAAA,EACA,UAAU;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACT;AAEO,aAAM,mBAAmB;AAAA,EAC9B,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACT;AAEO,aAAM,aAAa;AAAA,EACxB,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAK;AACP;AAEO,aAAM,aAAa;AAInB,aAAM,gBAAgB;AAAA,EAC3B,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,WAAW;AAAA,EACX,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,kBAAkB;AACpB;AAEO,aAAM,qBAAqB;AAAA,EAChC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AACZ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|