@openstax/ts-utils 1.34.1 → 1.35.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.
@@ -40,6 +40,8 @@ type Field = {
40
40
  export interface IndexOptions<T> {
41
41
  body: T;
42
42
  id: string;
43
+ version?: number;
44
+ version_type?: 'external' | 'external_gte';
43
45
  }
44
46
  export type FieldMapping = {
45
47
  type: 'keyword' | 'text' | 'boolean';
@@ -63,7 +63,9 @@ const openSearchService = (initializer = {}) => (configProvider) => {
63
63
  index: indexConfig.name,
64
64
  body: params.body,
65
65
  id: params.id,
66
- refresh: true
66
+ refresh: true,
67
+ version: params.version,
68
+ version_type: params.version_type
67
69
  }, {
68
70
  requestTimeout: 10000,
69
71
  maxRetries: 1,
@@ -74,7 +76,13 @@ const openSearchService = (initializer = {}) => (configProvider) => {
74
76
  await openSearchClient.bulk({
75
77
  index: indexConfig.name,
76
78
  body: items.flatMap((item) => [
77
- { index: { _id: item.id } },
79
+ {
80
+ index: {
81
+ _id: item.id,
82
+ ...(item.version !== undefined ? { version: item.version } : {}),
83
+ ...(item.version_type !== undefined ? { version_type: item.version_type } : {})
84
+ }
85
+ },
78
86
  item.body
79
87
  ]),
80
88
  refresh: true
@@ -0,0 +1,17 @@
1
+ import { DynamoDBRecord } from 'aws-lambda';
2
+ import { Logger } from '../logger';
3
+ import { IndexOptions } from '../searchProvider';
4
+ export interface SearchProvider<T> {
5
+ index: (options: IndexOptions<T>) => Promise<void>;
6
+ bulkIndex: (items: IndexOptions<T>[]) => Promise<void>;
7
+ }
8
+ export interface SearchIndexUpdaterConfig<T> {
9
+ searchProvider: SearchProvider<T>;
10
+ logger: Logger;
11
+ getDocumentId: (document: T) => string;
12
+ getDocumentVersion?: (document: T) => number | undefined;
13
+ }
14
+ /**
15
+ * Function to update search index from DynamoDB Stream records.
16
+ */
17
+ export declare const updateSearchIndexFromStream: <T>(records: DynamoDBRecord[], config: SearchIndexUpdaterConfig<T>) => Promise<void>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateSearchIndexFromStream = void 0;
4
+ const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
5
+ const logger_1 = require("../logger");
6
+ const VALID_EVENTS = new Set(['INSERT', 'MODIFY']);
7
+ /**
8
+ * Function to update search index from DynamoDB Stream records.
9
+ */
10
+ const updateSearchIndexFromStream = async (records, config) => {
11
+ var _a, _b;
12
+ const { searchProvider, logger, getDocumentId, getDocumentVersion } = config;
13
+ const itemsToIndex = [];
14
+ for (const record of records) {
15
+ if (!record.eventName || !VALID_EVENTS.has(record.eventName)) {
16
+ logger.log(`Skipping ${record.eventName || 'undefined'} event`, logger_1.Level.Error);
17
+ continue;
18
+ }
19
+ if (!((_a = record.dynamodb) === null || _a === void 0 ? void 0 : _a.NewImage)) {
20
+ logger.log('Missing NewImage in record, skipping', logger_1.Level.Error);
21
+ continue;
22
+ }
23
+ const document = (0, util_dynamodb_1.unmarshall)(record.dynamodb.NewImage);
24
+ const documentId = getDocumentId(document);
25
+ const indexOptions = {
26
+ id: documentId,
27
+ body: document,
28
+ };
29
+ const version = (_b = getDocumentVersion === null || getDocumentVersion === void 0 ? void 0 : getDocumentVersion(document)) !== null && _b !== void 0 ? _b : record.dynamodb.ApproximateCreationDateTime;
30
+ if (version !== undefined) {
31
+ indexOptions.version = version;
32
+ indexOptions.version_type = 'external';
33
+ }
34
+ itemsToIndex.push(indexOptions);
35
+ }
36
+ if (itemsToIndex.length > 0) {
37
+ await searchProvider.bulkIndex(itemsToIndex);
38
+ logger.log(`Successfully indexed ${itemsToIndex.length} documents`);
39
+ }
40
+ };
41
+ exports.updateSearchIndexFromStream = updateSearchIndexFromStream;