@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.
@@ -0,0 +1,3 @@
1
+ import { WebinyError } from "@webiny/error";
2
+ export declare class NotEnoughRemainingTimeError extends WebinyError {
3
+ }
@@ -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
@@ -1 +1,6 @@
1
+ export declare enum Operations {
2
+ INSERT = "INSERT",
3
+ MODIFY = "MODIFY",
4
+ REMOVE = "REMOVE"
5
+ }
1
6
  export declare const createEventHandler: () => import("@webiny/handler-aws").DynamoDBEventHandler<unknown>;
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 Operations = /*#__PURE__*/function (Operations) {
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
- }(Operations || {});
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
- * Wrap the code we need to run into the function, so it can be called within itself.
74
- */
75
- const execute = async () => {
76
- const operations = [];
77
- for (const record of event.Records) {
78
- const dynamodb = record.dynamodb;
79
- if (!dynamodb) {
80
- continue;
81
- }
82
- /**
83
- * TODO: figure out correct types
84
- */
85
- // @ts-expect-error
86
- const newImage = unmarshall(dynamodb.NewImage);
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
- // Note that with the `REMOVE` event, there is no `NewImage` property. Which means,
89
- // if the `newImage` is `undefined`, we are dealing with a `REMOVE` event and we still
90
- // need to process it.
91
- if (newImage && newImage.ignore === true) {
92
- continue;
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
- * TODO: figure out correct types
128
+ * We must decompress the data that is going into the Elasticsearch.
96
129
  */
97
- // @ts-expect-error
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
- * TODO: figure out correct types
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
- // @ts-expect-error
107
- const oldImage = unmarshall(dynamodb.OldImage);
108
- const operation = record.eventName;
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
- switch (record.eventName) {
133
- case Operations.INSERT:
134
- case Operations.MODIFY:
135
- if (newImage) {
136
- operations.push({
137
- index: {
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
- delete: {
149
+ index: {
147
150
  _id,
148
- _index: oldImage?.index || "unknown"
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
- break;
152
- default:
153
- break;
219
+ }
220
+ });
221
+ } catch (ex) {
222
+ if (ex instanceof _apiElasticsearch.UnhealthyClusterError || ex instanceof _apiElasticsearch.WaitingHealthyClusterAbortedError) {
223
+ throw ex;
154
224
  }
155
- }
156
- if (!operations.length) {
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 === "true") {
166
- const meta = error?.meta || {};
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
- await (0, _pRetry.default)(execute, {
178
- maxRetryTime,
179
- retries,
180
- minTimeout,
181
- maxTimeout,
182
- onFailedAttempt: error => {
183
- /**
184
- * We will only log attempts which are after 3/4 of total attempts.
185
- */
186
- if (error.attemptNumber < retries * 0.75) {
187
- return;
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
- console.error(`Attempt #${error.attemptNumber} failed.`);
190
- console.error(error.message);
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-beta.5",
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-beta.5",
16
- "@webiny/aws-sdk": "5.40.0-beta.5",
17
- "@webiny/error": "5.40.0-beta.5",
18
- "@webiny/handler-aws": "5.40.0-beta.5",
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-beta.5",
30
- "@webiny/plugins": "5.40.0-beta.5",
31
- "@webiny/project-utils": "5.40.0-beta.5",
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": "04482b686c63fdadebd4c6c1db7595af1140cfc7"
47
+ "gitHead": "e6ce53a387a9b1ab39aa8d15e4ed9be2359f17aa"
48
48
  }