@karmaniverous/entity-manager 0.1.2-1 → 2.0.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/README.md
CHANGED
|
@@ -221,7 +221,8 @@ This change can be accomplished with no breaking changes to existing implementat
|
|
|
221
221
|
* [new exports.EntityManager(options)](#new_module_entity-manager.EntityManager_new)
|
|
222
222
|
* [.addKeys(entityToken, item, [overwrite])](#module_entity-manager.EntityManager+addKeys) ⇒ <code>object</code>
|
|
223
223
|
* [.getKeySpace(entityToken, keyToken, item, timestamp)](#module_entity-manager.EntityManager+getKeySpace) ⇒ <code>Array.<string></code>
|
|
224
|
-
* [.query(entityToken, keyToken, item, shardQuery, [
|
|
224
|
+
* [.query(entityToken, keyToken, item, shardQuery, [options])](#module_entity-manager.EntityManager+query) ⇒ <code>Promise.<ShardedQueryResult></code>
|
|
225
|
+
* [.removeKeys(entityToken, item)](#module_entity-manager.EntityManager+removeKeys) ⇒ <code>object</code>
|
|
225
226
|
* _inner_
|
|
226
227
|
* [~ShardQueryResult](#module_entity-manager..ShardQueryResult) : <code>object</code>
|
|
227
228
|
* [~ShardQueryFunction](#module_entity-manager..ShardQueryFunction) ⇒ <code>Promise.<ShardQueryResult></code>
|
|
@@ -238,7 +239,8 @@ Manage DynamoDb entities.
|
|
|
238
239
|
* [new exports.EntityManager(options)](#new_module_entity-manager.EntityManager_new)
|
|
239
240
|
* [.addKeys(entityToken, item, [overwrite])](#module_entity-manager.EntityManager+addKeys) ⇒ <code>object</code>
|
|
240
241
|
* [.getKeySpace(entityToken, keyToken, item, timestamp)](#module_entity-manager.EntityManager+getKeySpace) ⇒ <code>Array.<string></code>
|
|
241
|
-
* [.query(entityToken, keyToken, item, shardQuery, [
|
|
242
|
+
* [.query(entityToken, keyToken, item, shardQuery, [options])](#module_entity-manager.EntityManager+query) ⇒ <code>Promise.<ShardedQueryResult></code>
|
|
243
|
+
* [.removeKeys(entityToken, item)](#module_entity-manager.EntityManager+removeKeys) ⇒ <code>object</code>
|
|
242
244
|
|
|
243
245
|
<a name="new_module_entity-manager.EntityManager_new"></a>
|
|
244
246
|
|
|
@@ -261,7 +263,7 @@ Create an EntityManager instance.
|
|
|
261
263
|
<a name="module_entity-manager.EntityManager+addKeys"></a>
|
|
262
264
|
|
|
263
265
|
#### entityManager.addKeys(entityToken, item, [overwrite]) ⇒ <code>object</code>
|
|
264
|
-
|
|
266
|
+
Add sharded keys to an entity item. Does not mutate original item.
|
|
265
267
|
|
|
266
268
|
**Kind**: instance method of [<code>EntityManager</code>](#module_entity-manager.EntityManager)
|
|
267
269
|
**Returns**: <code>object</code> - Decorated entity item.
|
|
@@ -301,7 +303,7 @@ Return an array of sharded keys valid for a given entity token & timestamp.
|
|
|
301
303
|
|
|
302
304
|
<a name="module_entity-manager.EntityManager+query"></a>
|
|
303
305
|
|
|
304
|
-
#### entityManager.query(entityToken, keyToken, item, shardQuery, [
|
|
306
|
+
#### entityManager.query(entityToken, keyToken, item, shardQuery, [options]) ⇒ <code>Promise.<ShardedQueryResult></code>
|
|
305
307
|
Query an entity across shards.
|
|
306
308
|
|
|
307
309
|
**Kind**: instance method of [<code>EntityManager</code>](#module_entity-manager.EntityManager)
|
|
@@ -313,7 +315,27 @@ Query an entity across shards.
|
|
|
313
315
|
| keyToken | <code>string</code> | Key token. |
|
|
314
316
|
| item | <code>object</code> | Entity item sufficiently populated to generate property keyToken. |
|
|
315
317
|
| shardQuery | <code>ShardQueryFunction</code> | Sharded query function. |
|
|
316
|
-
| [
|
|
318
|
+
| [options] | <code>object</code> | Options object. |
|
|
319
|
+
| [options.limit] | <code>number</code> | Request limit. |
|
|
320
|
+
| [options.pageKeys] | <code>object</code> | Map of shard page keys. |
|
|
321
|
+
|
|
322
|
+
<a name="module_entity-manager.EntityManager+removeKeys"></a>
|
|
323
|
+
|
|
324
|
+
#### entityManager.removeKeys(entityToken, item) ⇒ <code>object</code>
|
|
325
|
+
Remove sharded keys from an entity item. Does not mutate original item.
|
|
326
|
+
|
|
327
|
+
**Kind**: instance method of [<code>EntityManager</code>](#module_entity-manager.EntityManager)
|
|
328
|
+
**Returns**: <code>object</code> - Stripped entity item.
|
|
329
|
+
**Throws**:
|
|
330
|
+
|
|
331
|
+
- <code>Error</code> If entityToken is invalid.
|
|
332
|
+
- <code>Error</code> If item is invalid.
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
| Param | Type | Description |
|
|
336
|
+
| --- | --- | --- |
|
|
337
|
+
| entityToken | <code>string</code> | Entity token. |
|
|
338
|
+
| item | <code>object</code> | Entity item. |
|
|
317
339
|
|
|
318
340
|
<a name="module_entity-manager..ShardQueryResult"></a>
|
|
319
341
|
|
|
@@ -337,7 +359,9 @@ Shard query function
|
|
|
337
359
|
| Param | Type | Description |
|
|
338
360
|
| --- | --- | --- |
|
|
339
361
|
| shardedKey | <code>string</code> | Sharded key. |
|
|
340
|
-
| [
|
|
362
|
+
| [options] | <code>object</code> | Options object. |
|
|
363
|
+
| [options.limit] | <code>number</code> | Request limit. |
|
|
364
|
+
| [options.pageKey] | <code>\*</code> | Page key. |
|
|
341
365
|
|
|
342
366
|
<a name="module_entity-manager..ShardedQueryResult"></a>
|
|
343
367
|
|
|
@@ -4,12 +4,18 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.EntityManager = void 0;
|
|
7
|
-
var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined"));
|
|
8
7
|
var _map2 = _interopRequireDefault(require("lodash/map"));
|
|
8
|
+
var _size2 = _interopRequireDefault(require("lodash/size"));
|
|
9
|
+
var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
|
|
9
10
|
var _fromPairs2 = _interopRequireDefault(require("lodash/fromPairs"));
|
|
11
|
+
var _isPlainObject2 = _interopRequireDefault(require("lodash/isPlainObject"));
|
|
12
|
+
var _isInteger2 = _interopRequireDefault(require("lodash/isInteger"));
|
|
13
|
+
var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined"));
|
|
14
|
+
var _isFunction2 = _interopRequireDefault(require("lodash/isFunction"));
|
|
10
15
|
var _sortedUniq2 = _interopRequireDefault(require("lodash/sortedUniq"));
|
|
11
16
|
var _forEach2 = _interopRequireDefault(require("lodash/forEach"));
|
|
12
17
|
var _isNil2 = _interopRequireDefault(require("lodash/isNil"));
|
|
18
|
+
var _cloneDeep2 = _interopRequireDefault(require("lodash/cloneDeep"));
|
|
13
19
|
var _PrivateEntityManager = require("./PrivateEntityManager.js");
|
|
14
20
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
21
|
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
|
|
@@ -52,7 +58,7 @@ class EntityManager {
|
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
/**
|
|
55
|
-
*
|
|
61
|
+
* Add sharded keys to an entity item. Does not mutate original item.
|
|
56
62
|
*
|
|
57
63
|
* @param {string} entityToken - Entity token.
|
|
58
64
|
* @param {object} item - Entity item.
|
|
@@ -65,6 +71,12 @@ class EntityManager {
|
|
|
65
71
|
let overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
66
72
|
_classPrivateFieldGet(this, _entityManager).logger.debug(`adding sharded index keys to ${entityToken}${overwrite ? ' with overwrite' : ''}...`, item);
|
|
67
73
|
|
|
74
|
+
// Validate item.
|
|
75
|
+
_classPrivateFieldGet(this, _entityManager).validateItem(item);
|
|
76
|
+
|
|
77
|
+
// Clone item.
|
|
78
|
+
const newItem = (0, _cloneDeep2.default)(item);
|
|
79
|
+
|
|
68
80
|
// Get entity config.
|
|
69
81
|
const {
|
|
70
82
|
shardKeyToken
|
|
@@ -75,22 +87,21 @@ class EntityManager {
|
|
|
75
87
|
} = _classPrivateFieldGet(this, _entityManager).getEntityConfig(entityToken);
|
|
76
88
|
|
|
77
89
|
// Add shardKey.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
item[shardKeyToken] = _classPrivateFieldGet(this, _entityManager).getShardKey(entityToken, entityKey, timestamp);
|
|
90
|
+
if (overwrite || (0, _isNil2.default)(newItem[shardKeyToken])) {
|
|
91
|
+
const entityKey = sharding.entityKey(newItem);
|
|
92
|
+
const timestamp = sharding.timestamp(newItem);
|
|
93
|
+
newItem[shardKeyToken] = _classPrivateFieldGet(this, _entityManager).getShardKey(entityToken, entityKey, timestamp);
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
// Add keys.
|
|
86
97
|
(0, _forEach2.default)(keys, (getValue, key) => {
|
|
87
|
-
if (overwrite || (0, _isNil2.default)(
|
|
98
|
+
if (overwrite || (0, _isNil2.default)(newItem[key])) newItem[key] = getValue(newItem);
|
|
88
99
|
});
|
|
89
|
-
_classPrivateFieldGet(this, _entityManager).logger.debug('done',
|
|
100
|
+
_classPrivateFieldGet(this, _entityManager).logger.debug('done', newItem);
|
|
90
101
|
|
|
91
102
|
// Remove undefined shardKey.
|
|
92
|
-
if ((0, _isNil2.default)(
|
|
93
|
-
return
|
|
103
|
+
if ((0, _isNil2.default)(newItem[shardKeyToken])) delete newItem[shardKeyToken];
|
|
104
|
+
return newItem;
|
|
94
105
|
}
|
|
95
106
|
|
|
96
107
|
/**
|
|
@@ -129,7 +140,9 @@ class EntityManager {
|
|
|
129
140
|
*
|
|
130
141
|
* @callback ShardQueryFunction
|
|
131
142
|
* @param {string} shardedKey - Sharded key.
|
|
132
|
-
* @param {
|
|
143
|
+
* @param {object} [options] - Options object.
|
|
144
|
+
* @param {number} [options.limit] - Request limit.
|
|
145
|
+
* @param {*} [options.pageKey] - Page key.
|
|
133
146
|
* @returns {Promise<ShardQueryResult>} Sharded query result.
|
|
134
147
|
*/
|
|
135
148
|
|
|
@@ -146,31 +159,50 @@ class EntityManager {
|
|
|
146
159
|
* @param {string} keyToken - Key token.
|
|
147
160
|
* @param {object} item - Entity item sufficiently populated to generate property keyToken.
|
|
148
161
|
* @param {ShardQueryFunction} shardQuery - Sharded query function.
|
|
149
|
-
* @param {object} [
|
|
162
|
+
* @param {object} [options] - Options object.
|
|
163
|
+
* @param {number} [options.limit] - Request limit.
|
|
164
|
+
* @param {object} [options.pageKeys] - Map of shard page keys.
|
|
150
165
|
* @returns {Promise<ShardedQueryResult>} Sharded query result.
|
|
151
166
|
*/
|
|
152
|
-
async query(entityToken, keyToken, item, shardQuery
|
|
167
|
+
async query(entityToken, keyToken, item, shardQuery) {
|
|
168
|
+
let {
|
|
169
|
+
limit,
|
|
170
|
+
pageKeys
|
|
171
|
+
} = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
172
|
+
// Validate params.
|
|
173
|
+
_classPrivateFieldGet(this, _entityManager).validateKeyToken(entityToken, keyToken);
|
|
174
|
+
_classPrivateFieldGet(this, _entityManager).validateItem(item);
|
|
175
|
+
if (!(0, _isFunction2.default)(shardQuery)) throw new Error('shardQuery must be a function');
|
|
176
|
+
if (!(0, _isUndefined2.default)(limit) && !(0, _isInteger2.default)(limit)) throw new Error('limit must be an integer');
|
|
177
|
+
if (!(0, _isUndefined2.default)(pageKeys) && !(0, _isPlainObject2.default)(pageKeys)) throw new Error('pageKeys must be an object');
|
|
178
|
+
|
|
153
179
|
// Generate default pageKeys if not provided
|
|
154
180
|
pageKeys ??= (0, _fromPairs2.default)(this.getKeySpace(entityToken, keyToken, item).map(shardedKey => [shardedKey, undefined]));
|
|
155
181
|
|
|
182
|
+
// Return empty result if no pageKeys.
|
|
183
|
+
if ((0, _isEmpty2.default)(pageKeys)) return {
|
|
184
|
+
items: [],
|
|
185
|
+
pageKeys: {}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Calculate shard limit.
|
|
189
|
+
const shardLimit = (0, _isUndefined2.default)(limit) ? undefined : Math.ceil(limit / (0, _size2.default)(pageKeys));
|
|
190
|
+
|
|
156
191
|
// Query every shard in pageKeys.
|
|
157
|
-
const shardQueryResults = await Promise.all((0, _map2.default)(pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey,
|
|
192
|
+
const shardQueryResults = await Promise.all((0, _map2.default)(pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey, {
|
|
193
|
+
pageKey,
|
|
194
|
+
limit: shardLimit
|
|
195
|
+
}).then(_ref2 => {
|
|
158
196
|
let {
|
|
159
197
|
items,
|
|
160
198
|
pageKey
|
|
161
199
|
} = _ref2;
|
|
162
|
-
console.log('shardQueryResult', {
|
|
163
|
-
shardedKey,
|
|
164
|
-
items,
|
|
165
|
-
pageKey
|
|
166
|
-
});
|
|
167
200
|
return resolve({
|
|
168
201
|
shardedKey,
|
|
169
202
|
items,
|
|
170
203
|
pageKey
|
|
171
204
|
});
|
|
172
205
|
}))));
|
|
173
|
-
console.log('shardQueryResults', shardQueryResults);
|
|
174
206
|
|
|
175
207
|
// Reduce shardQueryResults into a single result.
|
|
176
208
|
const result = shardQueryResults.reduce((shardedQueryResult, _ref3) => {
|
|
@@ -194,5 +226,42 @@ class EntityManager {
|
|
|
194
226
|
});
|
|
195
227
|
return result;
|
|
196
228
|
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Remove sharded keys from an entity item. Does not mutate original item.
|
|
232
|
+
*
|
|
233
|
+
* @param {string} entityToken - Entity token.
|
|
234
|
+
* @param {object} item - Entity item.
|
|
235
|
+
* @returns {object} Stripped entity item.
|
|
236
|
+
* @throws {Error} If entityToken is invalid.
|
|
237
|
+
* @throws {Error} If item is invalid.
|
|
238
|
+
*/
|
|
239
|
+
removeKeys(entityToken, item) {
|
|
240
|
+
_classPrivateFieldGet(this, _entityManager).logger.debug(`removing sharded index keys from ${entityToken}...`, item);
|
|
241
|
+
|
|
242
|
+
// Validate item.
|
|
243
|
+
_classPrivateFieldGet(this, _entityManager).validateItem(item);
|
|
244
|
+
|
|
245
|
+
// Clone item.
|
|
246
|
+
const newItem = (0, _cloneDeep2.default)(item);
|
|
247
|
+
|
|
248
|
+
// Get entity config.
|
|
249
|
+
const {
|
|
250
|
+
shardKeyToken
|
|
251
|
+
} = _classPrivateFieldGet(this, _entityManager);
|
|
252
|
+
const {
|
|
253
|
+
keys
|
|
254
|
+
} = _classPrivateFieldGet(this, _entityManager).getEntityConfig(entityToken);
|
|
255
|
+
|
|
256
|
+
// Remove shardKey.
|
|
257
|
+
delete newItem[shardKeyToken];
|
|
258
|
+
|
|
259
|
+
// Remove keys.
|
|
260
|
+
(0, _forEach2.default)(keys, (getValue, key) => {
|
|
261
|
+
delete newItem[key];
|
|
262
|
+
});
|
|
263
|
+
_classPrivateFieldGet(this, _entityManager).logger.debug('done', newItem);
|
|
264
|
+
return newItem;
|
|
265
|
+
}
|
|
197
266
|
}
|
|
198
267
|
exports.EntityManager = EntityManager;
|
|
@@ -379,6 +379,22 @@ class PrivateEntityManager {
|
|
|
379
379
|
} else return true;
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Tests whether a key token is valid.
|
|
384
|
+
*
|
|
385
|
+
* @param {string} entityToken - Entity token.
|
|
386
|
+
* @param {string} keyToken - Key token.
|
|
387
|
+
* @returns {boolean} true if keyToken is valid.
|
|
388
|
+
*/
|
|
389
|
+
validateKeyToken(entityToken, keyToken) {
|
|
390
|
+
this.validateEntityToken(entityToken);
|
|
391
|
+
if (!this.config.entities[entityToken].keys[keyToken]) {
|
|
392
|
+
const message = `Invalid entity ${entityToken} keyToken: ${keyToken}`;
|
|
393
|
+
this.logger.error(message);
|
|
394
|
+
throw new Error(message);
|
|
395
|
+
} else return true;
|
|
396
|
+
}
|
|
397
|
+
|
|
382
398
|
/**
|
|
383
399
|
* Tests whether an item is valid.
|
|
384
400
|
*
|
|
@@ -29,7 +29,7 @@ export class EntityManager {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* Add sharded keys to an entity item. Does not mutate original item.
|
|
33
33
|
*
|
|
34
34
|
* @param {string} entityToken - Entity token.
|
|
35
35
|
* @param {object} item - Entity item.
|
|
@@ -46,16 +46,21 @@ export class EntityManager {
|
|
|
46
46
|
item
|
|
47
47
|
);
|
|
48
48
|
|
|
49
|
+
// Validate item.
|
|
50
|
+
this.#entityManager.validateItem(item);
|
|
51
|
+
|
|
52
|
+
// Clone item.
|
|
53
|
+
const newItem = _.cloneDeep(item);
|
|
54
|
+
|
|
49
55
|
// Get entity config.
|
|
50
56
|
const { shardKeyToken } = this.#entityManager;
|
|
51
57
|
const { keys, sharding } = this.#entityManager.getEntityConfig(entityToken);
|
|
52
58
|
|
|
53
59
|
// Add shardKey.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
item[shardKeyToken] = this.#entityManager.getShardKey(
|
|
60
|
+
if (overwrite || _.isNil(newItem[shardKeyToken])) {
|
|
61
|
+
const entityKey = sharding.entityKey(newItem);
|
|
62
|
+
const timestamp = sharding.timestamp(newItem);
|
|
63
|
+
newItem[shardKeyToken] = this.#entityManager.getShardKey(
|
|
59
64
|
entityToken,
|
|
60
65
|
entityKey,
|
|
61
66
|
timestamp
|
|
@@ -64,14 +69,14 @@ export class EntityManager {
|
|
|
64
69
|
|
|
65
70
|
// Add keys.
|
|
66
71
|
_.forEach(keys, (getValue, key) => {
|
|
67
|
-
if (overwrite || _.isNil(
|
|
72
|
+
if (overwrite || _.isNil(newItem[key])) newItem[key] = getValue(newItem);
|
|
68
73
|
});
|
|
69
|
-
this.#entityManager.logger.debug('done',
|
|
74
|
+
this.#entityManager.logger.debug('done', newItem);
|
|
70
75
|
|
|
71
76
|
// Remove undefined shardKey.
|
|
72
|
-
if (_.isNil(
|
|
77
|
+
if (_.isNil(newItem[shardKeyToken])) delete newItem[shardKeyToken];
|
|
73
78
|
|
|
74
|
-
return
|
|
79
|
+
return newItem;
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
/**
|
|
@@ -125,7 +130,9 @@ export class EntityManager {
|
|
|
125
130
|
*
|
|
126
131
|
* @callback ShardQueryFunction
|
|
127
132
|
* @param {string} shardedKey - Sharded key.
|
|
128
|
-
* @param {
|
|
133
|
+
* @param {object} [options] - Options object.
|
|
134
|
+
* @param {number} [options.limit] - Request limit.
|
|
135
|
+
* @param {*} [options.pageKey] - Page key.
|
|
129
136
|
* @returns {Promise<ShardQueryResult>} Sharded query result.
|
|
130
137
|
*/
|
|
131
138
|
|
|
@@ -142,10 +149,28 @@ export class EntityManager {
|
|
|
142
149
|
* @param {string} keyToken - Key token.
|
|
143
150
|
* @param {object} item - Entity item sufficiently populated to generate property keyToken.
|
|
144
151
|
* @param {ShardQueryFunction} shardQuery - Sharded query function.
|
|
145
|
-
* @param {object} [
|
|
152
|
+
* @param {object} [options] - Options object.
|
|
153
|
+
* @param {number} [options.limit] - Request limit.
|
|
154
|
+
* @param {object} [options.pageKeys] - Map of shard page keys.
|
|
146
155
|
* @returns {Promise<ShardedQueryResult>} Sharded query result.
|
|
147
156
|
*/
|
|
148
|
-
async query(
|
|
157
|
+
async query(
|
|
158
|
+
entityToken,
|
|
159
|
+
keyToken,
|
|
160
|
+
item,
|
|
161
|
+
shardQuery,
|
|
162
|
+
{ limit, pageKeys } = {}
|
|
163
|
+
) {
|
|
164
|
+
// Validate params.
|
|
165
|
+
this.#entityManager.validateKeyToken(entityToken, keyToken);
|
|
166
|
+
this.#entityManager.validateItem(item);
|
|
167
|
+
if (!_.isFunction(shardQuery))
|
|
168
|
+
throw new Error('shardQuery must be a function');
|
|
169
|
+
if (!_.isUndefined(limit) && !_.isInteger(limit))
|
|
170
|
+
throw new Error('limit must be an integer');
|
|
171
|
+
if (!_.isUndefined(pageKeys) && !_.isPlainObject(pageKeys))
|
|
172
|
+
throw new Error('pageKeys must be an object');
|
|
173
|
+
|
|
149
174
|
// Generate default pageKeys if not provided
|
|
150
175
|
pageKeys ??= _.fromPairs(
|
|
151
176
|
this.getKeySpace(entityToken, keyToken, item).map((shardedKey) => [
|
|
@@ -154,22 +179,27 @@ export class EntityManager {
|
|
|
154
179
|
])
|
|
155
180
|
);
|
|
156
181
|
|
|
182
|
+
// Return empty result if no pageKeys.
|
|
183
|
+
if (_.isEmpty(pageKeys)) return { items: [], pageKeys: {} };
|
|
184
|
+
|
|
185
|
+
// Calculate shard limit.
|
|
186
|
+
const shardLimit = _.isUndefined(limit)
|
|
187
|
+
? undefined
|
|
188
|
+
: Math.ceil(limit / _.size(pageKeys));
|
|
189
|
+
|
|
157
190
|
// Query every shard in pageKeys.
|
|
158
191
|
const shardQueryResults = await Promise.all(
|
|
159
192
|
_.map(
|
|
160
193
|
pageKeys,
|
|
161
194
|
(pageKey, shardedKey) =>
|
|
162
195
|
new Promise((resolve) =>
|
|
163
|
-
shardQuery(shardedKey,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
})
|
|
196
|
+
shardQuery(shardedKey, { pageKey, limit: shardLimit }).then(
|
|
197
|
+
({ items, pageKey }) => resolve({ shardedKey, items, pageKey })
|
|
198
|
+
)
|
|
167
199
|
)
|
|
168
200
|
)
|
|
169
201
|
);
|
|
170
202
|
|
|
171
|
-
console.log('shardQueryResults', shardQueryResults);
|
|
172
|
-
|
|
173
203
|
// Reduce shardQueryResults into a single result.
|
|
174
204
|
const result = shardQueryResults.reduce(
|
|
175
205
|
(shardedQueryResult, { shardedKey, items, pageKey }) => ({
|
|
@@ -184,4 +214,41 @@ export class EntityManager {
|
|
|
184
214
|
|
|
185
215
|
return result;
|
|
186
216
|
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Remove sharded keys from an entity item. Does not mutate original item.
|
|
220
|
+
*
|
|
221
|
+
* @param {string} entityToken - Entity token.
|
|
222
|
+
* @param {object} item - Entity item.
|
|
223
|
+
* @returns {object} Stripped entity item.
|
|
224
|
+
* @throws {Error} If entityToken is invalid.
|
|
225
|
+
* @throws {Error} If item is invalid.
|
|
226
|
+
*/
|
|
227
|
+
removeKeys(entityToken, item) {
|
|
228
|
+
this.#entityManager.logger.debug(
|
|
229
|
+
`removing sharded index keys from ${entityToken}...`,
|
|
230
|
+
item
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
// Validate item.
|
|
234
|
+
this.#entityManager.validateItem(item);
|
|
235
|
+
|
|
236
|
+
// Clone item.
|
|
237
|
+
const newItem = _.cloneDeep(item);
|
|
238
|
+
|
|
239
|
+
// Get entity config.
|
|
240
|
+
const { shardKeyToken } = this.#entityManager;
|
|
241
|
+
const { keys } = this.#entityManager.getEntityConfig(entityToken);
|
|
242
|
+
|
|
243
|
+
// Remove shardKey.
|
|
244
|
+
delete newItem[shardKeyToken];
|
|
245
|
+
|
|
246
|
+
// Remove keys.
|
|
247
|
+
_.forEach(keys, (getValue, key) => {
|
|
248
|
+
delete newItem[key];
|
|
249
|
+
});
|
|
250
|
+
this.#entityManager.logger.debug('done', newItem);
|
|
251
|
+
|
|
252
|
+
return newItem;
|
|
253
|
+
}
|
|
187
254
|
}
|
|
@@ -348,6 +348,23 @@ export class PrivateEntityManager {
|
|
|
348
348
|
} else return true;
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
/**
|
|
352
|
+
* Tests whether a key token is valid.
|
|
353
|
+
*
|
|
354
|
+
* @param {string} entityToken - Entity token.
|
|
355
|
+
* @param {string} keyToken - Key token.
|
|
356
|
+
* @returns {boolean} true if keyToken is valid.
|
|
357
|
+
*/
|
|
358
|
+
validateKeyToken(entityToken, keyToken) {
|
|
359
|
+
this.validateEntityToken(entityToken);
|
|
360
|
+
|
|
361
|
+
if (!this.config.entities[entityToken].keys[keyToken]) {
|
|
362
|
+
const message = `Invalid entity ${entityToken} keyToken: ${keyToken}`;
|
|
363
|
+
this.logger.error(message);
|
|
364
|
+
throw new Error(message);
|
|
365
|
+
} else return true;
|
|
366
|
+
}
|
|
367
|
+
|
|
351
368
|
/**
|
|
352
369
|
* Tests whether an item is valid.
|
|
353
370
|
*
|