@webiny/api-dynamodb-to-elasticsearch 5.40.0-beta.5 → 5.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NotEnoughRemainingTimeError.d.ts +3 -0
- package/NotEnoughRemainingTimeError.js +11 -0
- package/NotEnoughRemainingTimeError.js.map +1 -0
- package/index.d.ts +5 -0
- package/index.js +188 -106
- package/index.js.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.NotEnoughRemainingTimeError = void 0;
|
|
7
|
+
var _error = require("@webiny/error");
|
|
8
|
+
class NotEnoughRemainingTimeError extends _error.WebinyError {}
|
|
9
|
+
exports.NotEnoughRemainingTimeError = NotEnoughRemainingTimeError;
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=NotEnoughRemainingTimeError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_error","require","NotEnoughRemainingTimeError","WebinyError","exports"],"sources":["NotEnoughRemainingTimeError.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\n\nexport class NotEnoughRemainingTimeError extends WebinyError {}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEO,MAAMC,2BAA2B,SAASC,kBAAW,CAAC;AAAEC,OAAA,CAAAF,2BAAA,GAAAA,2BAAA","ignoreList":[]}
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -4,18 +4,20 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.createEventHandler = void 0;
|
|
7
|
+
exports.createEventHandler = exports.Operations = void 0;
|
|
8
8
|
var _error = _interopRequireDefault(require("@webiny/error"));
|
|
9
9
|
var _clientDynamodb = require("@webiny/aws-sdk/client-dynamodb");
|
|
10
10
|
var _apiElasticsearch = require("@webiny/api-elasticsearch");
|
|
11
11
|
var _handlerAws = require("@webiny/handler-aws");
|
|
12
|
+
var _types = require("@webiny/api-elasticsearch/operations/types");
|
|
12
13
|
var _pRetry = _interopRequireDefault(require("p-retry"));
|
|
13
|
-
var
|
|
14
|
+
var _NotEnoughRemainingTimeError = require("./NotEnoughRemainingTimeError");
|
|
15
|
+
let Operations = exports.Operations = /*#__PURE__*/function (Operations) {
|
|
14
16
|
Operations["INSERT"] = "INSERT";
|
|
15
17
|
Operations["MODIFY"] = "MODIFY";
|
|
16
18
|
Operations["REMOVE"] = "REMOVE";
|
|
17
19
|
return Operations;
|
|
18
|
-
}(
|
|
20
|
+
}({});
|
|
19
21
|
const getError = item => {
|
|
20
22
|
if (!item.index?.error?.reason) {
|
|
21
23
|
return null;
|
|
@@ -26,14 +28,6 @@ const getError = item => {
|
|
|
26
28
|
}
|
|
27
29
|
return reason;
|
|
28
30
|
};
|
|
29
|
-
const getNumberEnvVariable = (name, def) => {
|
|
30
|
-
const input = process.env[name];
|
|
31
|
-
const value = Number(input);
|
|
32
|
-
if (value > 0) {
|
|
33
|
-
return value;
|
|
34
|
-
}
|
|
35
|
-
return def;
|
|
36
|
-
};
|
|
37
31
|
const checkErrors = result => {
|
|
38
32
|
if (!result || !result.body || !result.body.items) {
|
|
39
33
|
return;
|
|
@@ -52,109 +46,184 @@ const checkErrors = result => {
|
|
|
52
46
|
throw new _error.default(err, "DYNAMODB_TO_ELASTICSEARCH_ERROR", item);
|
|
53
47
|
}
|
|
54
48
|
};
|
|
49
|
+
const getNumberEnvVariable = (name, def) => {
|
|
50
|
+
const input = process.env[name];
|
|
51
|
+
const value = Number(input);
|
|
52
|
+
if (isNaN(value)) {
|
|
53
|
+
return def;
|
|
54
|
+
} else if (value <= 0) {
|
|
55
|
+
return def;
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
};
|
|
59
|
+
const MAX_PROCESSOR_PERCENT = getNumberEnvVariable("MAX_ES_PROCESSOR", process.env.NODE_ENV === "test" ? 101 : 98);
|
|
55
60
|
const unmarshall = value => {
|
|
56
61
|
if (!value) {
|
|
57
62
|
return undefined;
|
|
58
63
|
}
|
|
59
64
|
return (0, _clientDynamodb.unmarshall)(value);
|
|
60
65
|
};
|
|
66
|
+
const minRemainingSecondsToTimeout = 120;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Also, we need to set the maximum running time for the Lambda Function.
|
|
70
|
+
* https://github.com/webiny/webiny-js/blob/f7352d418da2b5ae0b781376be46785aa7ac6ae0/packages/pulumi-aws/src/apps/core/CoreOpenSearch.ts#L232
|
|
71
|
+
* https://github.com/webiny/webiny-js/blob/f7352d418da2b5ae0b781376be46785aa7ac6ae0/packages/pulumi-aws/src/apps/core/CoreElasticSearch.ts#L218
|
|
72
|
+
*/
|
|
73
|
+
const MAX_RUNNING_TIME = 900;
|
|
61
74
|
const createEventHandler = () => {
|
|
62
75
|
return (0, _handlerAws.createDynamoDBEventHandler)(async ({
|
|
63
76
|
event,
|
|
64
|
-
context: ctx
|
|
77
|
+
context: ctx,
|
|
78
|
+
lambdaContext
|
|
65
79
|
}) => {
|
|
80
|
+
const timer = (0, _handlerAws.timerFactory)(lambdaContext);
|
|
66
81
|
const context = ctx;
|
|
67
82
|
if (!context.elasticsearch) {
|
|
68
83
|
console.error("Missing elasticsearch definition on context.");
|
|
69
84
|
return null;
|
|
70
85
|
}
|
|
86
|
+
const operations = [];
|
|
87
|
+
const operationIdList = [];
|
|
88
|
+
for (const record of event.Records) {
|
|
89
|
+
const dynamodb = record.dynamodb;
|
|
90
|
+
if (!dynamodb) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* TODO: figure out correct types
|
|
95
|
+
*/
|
|
96
|
+
// @ts-expect-error
|
|
97
|
+
const newImage = unmarshall(dynamodb.NewImage);
|
|
71
98
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
99
|
+
// Note that with the `REMOVE` event, there is no `NewImage` property. Which means,
|
|
100
|
+
// if the `newImage` is `undefined`, we are dealing with a `REMOVE` event and we still
|
|
101
|
+
// need to process it.
|
|
102
|
+
if (newImage && newImage.ignore === true) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* TODO: figure out correct types
|
|
107
|
+
*/
|
|
108
|
+
// @ts-expect-error
|
|
109
|
+
const keys = unmarshall(dynamodb.Keys);
|
|
110
|
+
if (!keys?.PK || !keys.SK) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const _id = `${keys.PK}:${keys.SK}`;
|
|
114
|
+
/**
|
|
115
|
+
* TODO: figure out correct types
|
|
116
|
+
*/
|
|
117
|
+
// @ts-expect-error
|
|
118
|
+
const oldImage = unmarshall(dynamodb.OldImage);
|
|
119
|
+
const operation = record.eventName;
|
|
87
120
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
121
|
+
/**
|
|
122
|
+
* On operations other than REMOVE we decompress the data and store it into the Elasticsearch.
|
|
123
|
+
* No need to try to decompress if operation is REMOVE since there is no data sent into that operation.
|
|
124
|
+
*/
|
|
125
|
+
let data = undefined;
|
|
126
|
+
if (newImage && operation !== Operations.REMOVE) {
|
|
94
127
|
/**
|
|
95
|
-
*
|
|
128
|
+
* We must decompress the data that is going into the Elasticsearch.
|
|
96
129
|
*/
|
|
97
|
-
|
|
98
|
-
const keys = unmarshall(dynamodb.Keys);
|
|
99
|
-
if (!keys?.PK || !keys.SK) {
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
const _id = `${keys.PK}:${keys.SK}`;
|
|
130
|
+
data = await (0, _apiElasticsearch.decompress)(context.plugins, newImage.data);
|
|
103
131
|
/**
|
|
104
|
-
*
|
|
132
|
+
* No point in writing null or undefined data into the Elasticsearch.
|
|
133
|
+
* This might happen on some error while decompressing. We will log it.
|
|
134
|
+
*
|
|
135
|
+
* Data should NEVER be null or undefined in the Elasticsearch DynamoDB table, unless it is a delete operations.
|
|
136
|
+
* If it is - it is a bug.
|
|
105
137
|
*/
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* On operations other than REMOVE we decompress the data and store it into the Elasticsearch.
|
|
112
|
-
* No need to try to decompress if operation is REMOVE since there is no data sent into that operation.
|
|
113
|
-
*/
|
|
114
|
-
let data = undefined;
|
|
115
|
-
if (newImage && operation !== Operations.REMOVE) {
|
|
116
|
-
/**
|
|
117
|
-
* We must decompress the data that is going into the Elasticsearch.
|
|
118
|
-
*/
|
|
119
|
-
data = await (0, _apiElasticsearch.decompress)(context.plugins, newImage.data);
|
|
120
|
-
/**
|
|
121
|
-
* No point in writing null or undefined data into the Elasticsearch.
|
|
122
|
-
* This might happen on some error while decompressing. We will log it.
|
|
123
|
-
*
|
|
124
|
-
* Data should NEVER be null or undefined in the Elasticsearch DynamoDB table, unless it is a delete operations.
|
|
125
|
-
* If it is - it is a bug.
|
|
126
|
-
*/
|
|
127
|
-
if (data === undefined || data === null) {
|
|
128
|
-
console.error(`Could not get decompressed data, skipping ES operation "${operation}", ID ${_id}`);
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
138
|
+
if (data === undefined || data === null) {
|
|
139
|
+
console.error(`Could not get decompressed data, skipping ES operation "${operation}", ID ${_id}`);
|
|
140
|
+
continue;
|
|
131
141
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
_id,
|
|
139
|
-
_index: newImage.index
|
|
140
|
-
}
|
|
141
|
-
}, data);
|
|
142
|
-
}
|
|
143
|
-
break;
|
|
144
|
-
case Operations.REMOVE:
|
|
142
|
+
}
|
|
143
|
+
operationIdList.push(_id);
|
|
144
|
+
switch (record.eventName) {
|
|
145
|
+
case Operations.INSERT:
|
|
146
|
+
case Operations.MODIFY:
|
|
147
|
+
if (newImage) {
|
|
145
148
|
operations.push({
|
|
146
|
-
|
|
149
|
+
index: {
|
|
147
150
|
_id,
|
|
148
|
-
_index:
|
|
151
|
+
_index: newImage.index
|
|
149
152
|
}
|
|
153
|
+
}, data);
|
|
154
|
+
}
|
|
155
|
+
break;
|
|
156
|
+
case Operations.REMOVE:
|
|
157
|
+
operations.push({
|
|
158
|
+
delete: {
|
|
159
|
+
_id,
|
|
160
|
+
_index: oldImage?.index || "unknown"
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
break;
|
|
164
|
+
default:
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* No need to do anything if there are no operations.
|
|
170
|
+
*/
|
|
171
|
+
if (operations.length === 0) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Wrap the code we need to run into the function, so it can be called within itself.
|
|
176
|
+
*/
|
|
177
|
+
const execute = async () => {
|
|
178
|
+
const remainingTime = timer.getRemainingSeconds();
|
|
179
|
+
const runningTime = MAX_RUNNING_TIME - remainingTime;
|
|
180
|
+
const maxWaitingTime = remainingTime - 90;
|
|
181
|
+
if (process.env.DEBUG === "true") {
|
|
182
|
+
console.debug(`The Lambda is already running for ${runningTime}s. Setting Health Check max waiting time: ${maxWaitingTime}s`);
|
|
183
|
+
}
|
|
184
|
+
const healthCheck = (0, _apiElasticsearch.createWaitUntilHealthy)(context.elasticsearch, {
|
|
185
|
+
minClusterHealthStatus: _types.ElasticsearchCatClusterHealthStatus.Yellow,
|
|
186
|
+
waitingTimeStep: 30,
|
|
187
|
+
maxProcessorPercent: MAX_PROCESSOR_PERCENT,
|
|
188
|
+
maxWaitingTime
|
|
189
|
+
});
|
|
190
|
+
try {
|
|
191
|
+
await healthCheck.wait({
|
|
192
|
+
async onUnhealthy({
|
|
193
|
+
startedAt,
|
|
194
|
+
runs,
|
|
195
|
+
mustEndAt,
|
|
196
|
+
waitingTimeStep,
|
|
197
|
+
waitingReason
|
|
198
|
+
}) {
|
|
199
|
+
console.debug(`Cluster is unhealthy on run #${runs}.`, {
|
|
200
|
+
startedAt,
|
|
201
|
+
mustEndAt,
|
|
202
|
+
waitingTimeStep,
|
|
203
|
+
waitingReason
|
|
204
|
+
});
|
|
205
|
+
},
|
|
206
|
+
async onTimeout({
|
|
207
|
+
startedAt,
|
|
208
|
+
runs,
|
|
209
|
+
waitingTimeStep,
|
|
210
|
+
mustEndAt,
|
|
211
|
+
waitingReason
|
|
212
|
+
}) {
|
|
213
|
+
console.error(`Cluster health check timeout on run #${runs}.`, {
|
|
214
|
+
startedAt,
|
|
215
|
+
mustEndAt,
|
|
216
|
+
waitingTimeStep,
|
|
217
|
+
waitingReason
|
|
150
218
|
});
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
} catch (ex) {
|
|
222
|
+
if (ex instanceof _apiElasticsearch.UnhealthyClusterError || ex instanceof _apiElasticsearch.WaitingHealthyClusterAbortedError) {
|
|
223
|
+
throw ex;
|
|
154
224
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return;
|
|
225
|
+
console.error(`Cluster health check failed.`, ex);
|
|
226
|
+
throw ex;
|
|
158
227
|
}
|
|
159
228
|
try {
|
|
160
229
|
const res = await context.elasticsearch.bulk({
|
|
@@ -162,34 +231,47 @@ const createEventHandler = () => {
|
|
|
162
231
|
});
|
|
163
232
|
checkErrors(res);
|
|
164
233
|
} catch (error) {
|
|
165
|
-
if (process.env.DEBUG
|
|
166
|
-
|
|
167
|
-
delete meta["meta"];
|
|
168
|
-
console.error("Bulk error", JSON.stringify(error, null, 2));
|
|
234
|
+
if (process.env.DEBUG !== "true") {
|
|
235
|
+
throw error;
|
|
169
236
|
}
|
|
237
|
+
const meta = error?.meta || {};
|
|
238
|
+
delete meta["meta"];
|
|
239
|
+
console.error("Bulk error", JSON.stringify(error, null, 2));
|
|
170
240
|
throw error;
|
|
171
241
|
}
|
|
242
|
+
if (process.env.DEBUG !== "true") {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
console.info(`Transferred ${operations.length / 2} record operations to Elasticsearch.`);
|
|
172
246
|
};
|
|
173
247
|
const maxRetryTime = getNumberEnvVariable("WEBINY_DYNAMODB_TO_ELASTICSEARCH_MAX_RETRY_TIME", 300000);
|
|
174
248
|
const retries = getNumberEnvVariable("WEBINY_DYNAMODB_TO_ELASTICSEARCH_RETRIES", 20);
|
|
175
249
|
const minTimeout = getNumberEnvVariable("WEBINY_DYNAMODB_TO_ELASTICSEARCH_MIN_TIMEOUT", 1500);
|
|
176
250
|
const maxTimeout = getNumberEnvVariable("WEBINY_DYNAMODB_TO_ELASTICSEARCH_MAX_TIMEOUT", 30000);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
251
|
+
try {
|
|
252
|
+
await (0, _pRetry.default)(execute, {
|
|
253
|
+
maxRetryTime,
|
|
254
|
+
retries,
|
|
255
|
+
minTimeout,
|
|
256
|
+
maxTimeout,
|
|
257
|
+
onFailedAttempt: error => {
|
|
258
|
+
if (timer.getRemainingSeconds() < minRemainingSecondsToTimeout) {
|
|
259
|
+
throw new _NotEnoughRemainingTimeError.NotEnoughRemainingTimeError(error);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* We will only log attempts which are after 3/4 of total attempts.
|
|
263
|
+
*/
|
|
264
|
+
if (error.attemptNumber < retries * 0.75) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
console.error(`Attempt #${error.attemptNumber} failed.`);
|
|
268
|
+
console.error(error);
|
|
188
269
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
270
|
+
});
|
|
271
|
+
} catch (ex) {
|
|
272
|
+
// TODO implement storing of failed operations
|
|
273
|
+
throw ex;
|
|
274
|
+
}
|
|
193
275
|
return null;
|
|
194
276
|
});
|
|
195
277
|
};
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_error","_interopRequireDefault","require","_clientDynamodb","_apiElasticsearch","_handlerAws","_pRetry","Operations","getError","item","index","error","reason","match","getNumberEnvVariable","name","def","input","process","env","value","Number","checkErrors","result","body","items","err","DEBUG","console","JSON","stringify","WebinyError","unmarshall","undefined","baseUnmarshall","createEventHandler","createDynamoDBEventHandler","event","context","ctx","elasticsearch","execute","operations","record","Records","dynamodb","newImage","NewImage","ignore","keys","Keys","PK","SK","_id","oldImage","OldImage","operation","eventName","data","REMOVE","decompress","plugins","INSERT","MODIFY","push","_index","delete","length","res","bulk","meta","maxRetryTime","retries","minTimeout","maxTimeout","pRetry","onFailedAttempt","attemptNumber","message","exports"],"sources":["index.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport { AttributeValue, unmarshall as baseUnmarshall } from \"@webiny/aws-sdk/client-dynamodb\";\nimport { decompress } from \"@webiny/api-elasticsearch\";\nimport { ApiResponse, ElasticsearchContext } from \"@webiny/api-elasticsearch/types\";\nimport { createDynamoDBEventHandler } from \"@webiny/handler-aws\";\nimport pRetry from \"p-retry\";\n\nenum Operations {\n INSERT = \"INSERT\",\n MODIFY = \"MODIFY\",\n REMOVE = \"REMOVE\"\n}\n\ninterface BulkOperationsResponseBodyItemIndexError {\n reason?: string;\n}\n\ninterface BulkOperationsResponseBodyItemIndex {\n error?: BulkOperationsResponseBodyItemIndexError;\n}\n\ninterface BulkOperationsResponseBodyItem {\n index?: BulkOperationsResponseBodyItemIndex;\n error?: string;\n}\n\ninterface BulkOperationsResponseBody {\n items: BulkOperationsResponseBodyItem[];\n}\n\nconst getError = (item: BulkOperationsResponseBodyItem): string | null => {\n if (!item.index?.error?.reason) {\n return null;\n }\n const reason = item.index.error.reason;\n if (reason.match(/no such index \\[([a-zA-Z0-9_-]+)\\]/) !== null) {\n return \"index\";\n }\n return reason;\n};\n\nconst getNumberEnvVariable = (name: string, def: number): number => {\n const input = process.env[name];\n const value = Number(input);\n if (value > 0) {\n return value;\n }\n return def;\n};\n\nconst checkErrors = (result?: ApiResponse<BulkOperationsResponseBody>): void => {\n if (!result || !result.body || !result.body.items) {\n return;\n }\n for (const item of result.body.items) {\n const err = getError(item);\n if (!err) {\n continue;\n } else if (err === \"index\") {\n if (process.env.DEBUG === \"true\") {\n console.error(\"Bulk response\", JSON.stringify(result, null, 2));\n }\n continue;\n }\n console.error(item.error);\n throw new WebinyError(err, \"DYNAMODB_TO_ELASTICSEARCH_ERROR\", item);\n }\n};\n\ninterface RecordDynamoDbImage {\n data: Record<string, any>;\n ignore?: boolean;\n index: string;\n}\n\ninterface RecordDynamoDbKeys {\n PK: string;\n SK: string;\n}\n\nconst unmarshall = <T>(value?: Record<string, AttributeValue>): T | undefined => {\n if (!value) {\n return undefined;\n }\n return baseUnmarshall(value) as T;\n};\n\nexport const createEventHandler = () => {\n return createDynamoDBEventHandler(async ({ event, context: ctx }) => {\n const context = ctx as unknown as ElasticsearchContext;\n if (!context.elasticsearch) {\n console.error(\"Missing elasticsearch definition on context.\");\n return null;\n }\n\n /**\n * Wrap the code we need to run into the function, so it can be called within itself.\n */\n const execute = async (): Promise<void> => {\n const operations = [];\n\n for (const record of event.Records) {\n const dynamodb = record.dynamodb;\n if (!dynamodb) {\n continue;\n }\n /**\n * TODO: figure out correct types\n */\n // @ts-expect-error\n const newImage = unmarshall<RecordDynamoDbImage>(dynamodb.NewImage);\n\n // Note that with the `REMOVE` event, there is no `NewImage` property. Which means,\n // if the `newImage` is `undefined`, we are dealing with a `REMOVE` event and we still\n // need to process it.\n if (newImage && newImage.ignore === true) {\n continue;\n }\n /**\n * TODO: figure out correct types\n */\n // @ts-expect-error\n const keys = unmarshall<RecordDynamoDbKeys>(dynamodb.Keys);\n if (!keys?.PK || !keys.SK) {\n continue;\n }\n const _id = `${keys.PK}:${keys.SK}`;\n /**\n * TODO: figure out correct types\n */\n // @ts-expect-error\n const oldImage = unmarshall<RecordDynamoDbImage>(dynamodb.OldImage);\n const operation = record.eventName;\n\n /**\n * On operations other than REMOVE we decompress the data and store it into the Elasticsearch.\n * No need to try to decompress if operation is REMOVE since there is no data sent into that operation.\n */\n let data: any = undefined;\n if (newImage && operation !== Operations.REMOVE) {\n /**\n * We must decompress the data that is going into the Elasticsearch.\n */\n data = await decompress(context.plugins, newImage.data);\n /**\n * No point in writing null or undefined data into the Elasticsearch.\n * This might happen on some error while decompressing. We will log it.\n *\n * Data should NEVER be null or undefined in the Elasticsearch DynamoDB table, unless it is a delete operations.\n * If it is - it is a bug.\n */\n if (data === undefined || data === null) {\n console.error(\n `Could not get decompressed data, skipping ES operation \"${operation}\", ID ${_id}`\n );\n continue;\n }\n }\n\n switch (record.eventName) {\n case Operations.INSERT:\n case Operations.MODIFY:\n if (newImage) {\n operations.push(\n {\n index: {\n _id,\n _index: newImage.index\n }\n },\n data\n );\n }\n break;\n case Operations.REMOVE:\n operations.push({\n delete: {\n _id,\n _index: oldImage?.index || \"unknown\"\n }\n });\n break;\n default:\n break;\n }\n }\n\n if (!operations.length) {\n return;\n }\n\n try {\n const res = await context.elasticsearch.bulk<BulkOperationsResponseBody>({\n body: operations\n });\n checkErrors(res);\n } catch (error) {\n if (process.env.DEBUG === \"true\") {\n const meta = error?.meta || {};\n delete meta[\"meta\"];\n console.error(\"Bulk error\", JSON.stringify(error, null, 2));\n }\n throw error;\n }\n };\n\n const maxRetryTime = getNumberEnvVariable(\n \"WEBINY_DYNAMODB_TO_ELASTICSEARCH_MAX_RETRY_TIME\",\n 300000\n );\n const retries = getNumberEnvVariable(\"WEBINY_DYNAMODB_TO_ELASTICSEARCH_RETRIES\", 20);\n const minTimeout = getNumberEnvVariable(\n \"WEBINY_DYNAMODB_TO_ELASTICSEARCH_MIN_TIMEOUT\",\n 1500\n );\n const maxTimeout = getNumberEnvVariable(\n \"WEBINY_DYNAMODB_TO_ELASTICSEARCH_MAX_TIMEOUT\",\n 30000\n );\n\n await pRetry(execute, {\n maxRetryTime,\n retries,\n minTimeout,\n maxTimeout,\n onFailedAttempt: error => {\n /**\n * We will only log attempts which are after 3/4 of total attempts.\n */\n if (error.attemptNumber < retries * 0.75) {\n return;\n }\n console.error(`Attempt #${error.attemptNumber} failed.`);\n console.error(error.message);\n }\n });\n\n return null;\n });\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_error","_interopRequireDefault","require","_clientDynamodb","_apiElasticsearch","_handlerAws","_types","_pRetry","_NotEnoughRemainingTimeError","Operations","exports","getError","item","index","error","reason","match","checkErrors","result","body","items","err","process","env","DEBUG","console","JSON","stringify","WebinyError","getNumberEnvVariable","name","def","input","value","Number","isNaN","MAX_PROCESSOR_PERCENT","NODE_ENV","unmarshall","undefined","baseUnmarshall","minRemainingSecondsToTimeout","MAX_RUNNING_TIME","createEventHandler","createDynamoDBEventHandler","event","context","ctx","lambdaContext","timer","timerFactory","elasticsearch","operations","operationIdList","record","Records","dynamodb","newImage","NewImage","ignore","keys","Keys","PK","SK","_id","oldImage","OldImage","operation","eventName","data","REMOVE","decompress","plugins","push","INSERT","MODIFY","_index","delete","length","execute","remainingTime","getRemainingSeconds","runningTime","maxWaitingTime","debug","healthCheck","createWaitUntilHealthy","minClusterHealthStatus","ElasticsearchCatClusterHealthStatus","Yellow","waitingTimeStep","maxProcessorPercent","wait","onUnhealthy","startedAt","runs","mustEndAt","waitingReason","onTimeout","ex","UnhealthyClusterError","WaitingHealthyClusterAbortedError","res","bulk","meta","info","maxRetryTime","retries","minTimeout","maxTimeout","pRetry","onFailedAttempt","NotEnoughRemainingTimeError","attemptNumber"],"sources":["index.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport { AttributeValue, unmarshall as baseUnmarshall } from \"@webiny/aws-sdk/client-dynamodb\";\nimport {\n createWaitUntilHealthy,\n decompress,\n UnhealthyClusterError,\n WaitingHealthyClusterAbortedError\n} from \"@webiny/api-elasticsearch\";\nimport { ApiResponse, ElasticsearchContext } from \"@webiny/api-elasticsearch/types\";\nimport { createDynamoDBEventHandler, timerFactory } from \"@webiny/handler-aws\";\nimport { ElasticsearchCatClusterHealthStatus } from \"@webiny/api-elasticsearch/operations/types\";\nimport pRetry from \"p-retry\";\nimport { NotEnoughRemainingTimeError } from \"./NotEnoughRemainingTimeError\";\n\nexport enum Operations {\n INSERT = \"INSERT\",\n MODIFY = \"MODIFY\",\n REMOVE = \"REMOVE\"\n}\n\ninterface BulkOperationsResponseBodyItemIndexError {\n reason?: string;\n}\n\ninterface BulkOperationsResponseBodyItemIndex {\n error?: BulkOperationsResponseBodyItemIndexError;\n}\n\ninterface BulkOperationsResponseBodyItem {\n index?: BulkOperationsResponseBodyItemIndex;\n error?: string;\n}\n\ninterface BulkOperationsResponseBody {\n items: BulkOperationsResponseBodyItem[];\n}\n\nconst getError = (item: BulkOperationsResponseBodyItem): string | null => {\n if (!item.index?.error?.reason) {\n return null;\n }\n const reason = item.index.error.reason;\n if (reason.match(/no such index \\[([a-zA-Z0-9_-]+)\\]/) !== null) {\n return \"index\";\n }\n return reason;\n};\n\nconst checkErrors = (result?: ApiResponse<BulkOperationsResponseBody>): void => {\n if (!result || !result.body || !result.body.items) {\n return;\n }\n for (const item of result.body.items) {\n const err = getError(item);\n if (!err) {\n continue;\n } else if (err === \"index\") {\n if (process.env.DEBUG === \"true\") {\n console.error(\"Bulk response\", JSON.stringify(result, null, 2));\n }\n continue;\n }\n console.error(item.error);\n throw new WebinyError(err, \"DYNAMODB_TO_ELASTICSEARCH_ERROR\", item);\n }\n};\n\nconst getNumberEnvVariable = (name: string, def: number): number => {\n const input = process.env[name];\n const value = Number(input);\n if (isNaN(value)) {\n return def;\n } else if (value <= 0) {\n return def;\n }\n return value;\n};\n\nconst MAX_PROCESSOR_PERCENT = getNumberEnvVariable(\n \"MAX_ES_PROCESSOR\",\n process.env.NODE_ENV === \"test\" ? 101 : 98\n);\n\ninterface RecordDynamoDbImage {\n data: Record<string, any>;\n ignore?: boolean;\n index: string;\n}\n\ninterface RecordDynamoDbKeys {\n PK: string;\n SK: string;\n}\n\nconst unmarshall = <T>(value?: Record<string, AttributeValue>): T | undefined => {\n if (!value) {\n return undefined;\n }\n return baseUnmarshall(value) as T;\n};\n\nconst minRemainingSecondsToTimeout = 120;\n\n/**\n * Also, we need to set the maximum running time for the Lambda Function.\n * https://github.com/webiny/webiny-js/blob/f7352d418da2b5ae0b781376be46785aa7ac6ae0/packages/pulumi-aws/src/apps/core/CoreOpenSearch.ts#L232\n * https://github.com/webiny/webiny-js/blob/f7352d418da2b5ae0b781376be46785aa7ac6ae0/packages/pulumi-aws/src/apps/core/CoreElasticSearch.ts#L218\n */\nconst MAX_RUNNING_TIME = 900;\n\nexport const createEventHandler = () => {\n return createDynamoDBEventHandler(async ({ event, context: ctx, lambdaContext }) => {\n const timer = timerFactory(lambdaContext);\n const context = ctx as unknown as ElasticsearchContext;\n if (!context.elasticsearch) {\n console.error(\"Missing elasticsearch definition on context.\");\n return null;\n }\n\n const operations: Record<string, any>[] = [];\n\n const operationIdList: string[] = [];\n\n for (const record of event.Records) {\n const dynamodb = record.dynamodb;\n if (!dynamodb) {\n continue;\n }\n /**\n * TODO: figure out correct types\n */\n // @ts-expect-error\n const newImage = unmarshall<RecordDynamoDbImage>(dynamodb.NewImage);\n\n // Note that with the `REMOVE` event, there is no `NewImage` property. Which means,\n // if the `newImage` is `undefined`, we are dealing with a `REMOVE` event and we still\n // need to process it.\n if (newImage && newImage.ignore === true) {\n continue;\n }\n /**\n * TODO: figure out correct types\n */\n // @ts-expect-error\n const keys = unmarshall<RecordDynamoDbKeys>(dynamodb.Keys);\n if (!keys?.PK || !keys.SK) {\n continue;\n }\n const _id = `${keys.PK}:${keys.SK}`;\n /**\n * TODO: figure out correct types\n */\n // @ts-expect-error\n const oldImage = unmarshall<RecordDynamoDbImage>(dynamodb.OldImage);\n const operation = record.eventName;\n\n /**\n * On operations other than REMOVE we decompress the data and store it into the Elasticsearch.\n * No need to try to decompress if operation is REMOVE since there is no data sent into that operation.\n */\n let data: any = undefined;\n if (newImage && operation !== Operations.REMOVE) {\n /**\n * We must decompress the data that is going into the Elasticsearch.\n */\n data = await decompress(context.plugins, newImage.data);\n /**\n * No point in writing null or undefined data into the Elasticsearch.\n * This might happen on some error while decompressing. We will log it.\n *\n * Data should NEVER be null or undefined in the Elasticsearch DynamoDB table, unless it is a delete operations.\n * If it is - it is a bug.\n */\n if (data === undefined || data === null) {\n console.error(\n `Could not get decompressed data, skipping ES operation \"${operation}\", ID ${_id}`\n );\n continue;\n }\n }\n\n operationIdList.push(_id);\n\n switch (record.eventName) {\n case Operations.INSERT:\n case Operations.MODIFY:\n if (newImage) {\n operations.push(\n {\n index: {\n _id,\n _index: newImage.index\n }\n },\n data\n );\n }\n break;\n case Operations.REMOVE:\n operations.push({\n delete: {\n _id,\n _index: oldImage?.index || \"unknown\"\n }\n });\n break;\n default:\n break;\n }\n }\n /**\n * No need to do anything if there are no operations.\n */\n if (operations.length === 0) {\n return null;\n }\n /**\n * Wrap the code we need to run into the function, so it can be called within itself.\n */\n const execute = async (): Promise<void> => {\n const remainingTime = timer.getRemainingSeconds();\n const runningTime = MAX_RUNNING_TIME - remainingTime;\n const maxWaitingTime = remainingTime - 90;\n\n if (process.env.DEBUG === \"true\") {\n console.debug(\n `The Lambda is already running for ${runningTime}s. Setting Health Check max waiting time: ${maxWaitingTime}s`\n );\n }\n\n const healthCheck = createWaitUntilHealthy(context.elasticsearch, {\n minClusterHealthStatus: ElasticsearchCatClusterHealthStatus.Yellow,\n waitingTimeStep: 30,\n maxProcessorPercent: MAX_PROCESSOR_PERCENT,\n maxWaitingTime\n });\n\n try {\n await healthCheck.wait({\n async onUnhealthy({\n startedAt,\n runs,\n mustEndAt,\n waitingTimeStep,\n waitingReason\n }) {\n console.debug(`Cluster is unhealthy on run #${runs}.`, {\n startedAt,\n mustEndAt,\n waitingTimeStep,\n waitingReason\n });\n },\n async onTimeout({\n startedAt,\n runs,\n waitingTimeStep,\n mustEndAt,\n waitingReason\n }) {\n console.error(`Cluster health check timeout on run #${runs}.`, {\n startedAt,\n mustEndAt,\n waitingTimeStep,\n waitingReason\n });\n }\n });\n } catch (ex) {\n if (\n ex instanceof UnhealthyClusterError ||\n ex instanceof WaitingHealthyClusterAbortedError\n ) {\n throw ex;\n }\n console.error(`Cluster health check failed.`, ex);\n throw ex;\n }\n\n try {\n const res = await context.elasticsearch.bulk<BulkOperationsResponseBody>({\n body: operations\n });\n checkErrors(res);\n } catch (error) {\n if (process.env.DEBUG !== \"true\") {\n throw error;\n }\n const meta = error?.meta || {};\n delete meta[\"meta\"];\n console.error(\"Bulk error\", JSON.stringify(error, null, 2));\n throw error;\n }\n if (process.env.DEBUG !== \"true\") {\n return;\n }\n console.info(\n `Transferred ${operations.length / 2} record operations to Elasticsearch.`\n );\n };\n\n const maxRetryTime = getNumberEnvVariable(\n \"WEBINY_DYNAMODB_TO_ELASTICSEARCH_MAX_RETRY_TIME\",\n 300000\n );\n const retries = getNumberEnvVariable(\"WEBINY_DYNAMODB_TO_ELASTICSEARCH_RETRIES\", 20);\n const minTimeout = getNumberEnvVariable(\n \"WEBINY_DYNAMODB_TO_ELASTICSEARCH_MIN_TIMEOUT\",\n 1500\n );\n const maxTimeout = getNumberEnvVariable(\n \"WEBINY_DYNAMODB_TO_ELASTICSEARCH_MAX_TIMEOUT\",\n 30000\n );\n\n try {\n await pRetry(execute, {\n maxRetryTime,\n retries,\n minTimeout,\n maxTimeout,\n onFailedAttempt: error => {\n if (timer.getRemainingSeconds() < minRemainingSecondsToTimeout) {\n throw new NotEnoughRemainingTimeError(error);\n }\n /**\n * We will only log attempts which are after 3/4 of total attempts.\n */\n if (error.attemptNumber < retries * 0.75) {\n return;\n }\n console.error(`Attempt #${error.attemptNumber} failed.`);\n console.error(error);\n }\n });\n } catch (ex) {\n // TODO implement storing of failed operations\n throw ex;\n }\n\n return null;\n });\n};\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/api-dynamodb-to-elasticsearch",
|
|
3
|
-
"version": "5.40.0
|
|
3
|
+
"version": "5.40.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"author": "Webiny Ltd.",
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@babel/runtime": "7.24.1",
|
|
15
|
-
"@webiny/api-elasticsearch": "5.40.0
|
|
16
|
-
"@webiny/aws-sdk": "5.40.0
|
|
17
|
-
"@webiny/error": "5.40.0
|
|
18
|
-
"@webiny/handler-aws": "5.40.0
|
|
15
|
+
"@webiny/api-elasticsearch": "5.40.0",
|
|
16
|
+
"@webiny/aws-sdk": "5.40.0",
|
|
17
|
+
"@webiny/error": "5.40.0",
|
|
18
|
+
"@webiny/handler-aws": "5.40.0",
|
|
19
19
|
"p-retry": "4.6.2"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"@babel/preset-env": "7.24.3",
|
|
27
27
|
"@babel/preset-typescript": "7.24.1",
|
|
28
28
|
"@types/aws-lambda": "8.10.136",
|
|
29
|
-
"@webiny/cli": "5.40.0
|
|
30
|
-
"@webiny/plugins": "5.40.0
|
|
31
|
-
"@webiny/project-utils": "5.40.0
|
|
29
|
+
"@webiny/cli": "5.40.0",
|
|
30
|
+
"@webiny/plugins": "5.40.0",
|
|
31
|
+
"@webiny/project-utils": "5.40.0",
|
|
32
32
|
"typescript": "4.7.4"
|
|
33
33
|
},
|
|
34
34
|
"publishConfig": {
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"__tests__"
|
|
45
45
|
]
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "e6ce53a387a9b1ab39aa8d15e4ed9be2359f17aa"
|
|
48
48
|
}
|