@karmaniverous/entity-manager 4.4.2 → 5.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
|
@@ -373,7 +373,7 @@ Query an entity across shards.
|
|
|
373
373
|
| options.shardQuery | <code>ShardQueryFunction</code> | Sharded query function. |
|
|
374
374
|
| [options.limit] | <code>number</code> | Request limit. |
|
|
375
375
|
| [options.pageKeys] | <code>object</code> | Map of shard page keys. |
|
|
376
|
-
| [options.
|
|
376
|
+
| [options.pageSize] | <code>number</code> | Request page size. |
|
|
377
377
|
|
|
378
378
|
<a name="module_entity-manager.EntityManager+rehydrateIndex"></a>
|
|
379
379
|
|
|
@@ -435,8 +435,8 @@ Shard query function
|
|
|
435
435
|
| Param | Type | Description |
|
|
436
436
|
| --- | --- | --- |
|
|
437
437
|
| shardedKey | <code>string</code> | Sharded key. |
|
|
438
|
-
| [limit] | <code>number</code> | Request limit. |
|
|
439
438
|
| [pageKey] | <code>\*</code> | Page key. |
|
|
439
|
+
| [limit] | <code>number</code> | Request limit. |
|
|
440
440
|
|
|
441
441
|
<a name="module_entity-manager..ShardedQueryResult"></a>
|
|
442
442
|
|
|
@@ -6,11 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.EntityManager = void 0;
|
|
7
7
|
var _zipObject2 = _interopRequireDefault(require("lodash/zipObject"));
|
|
8
8
|
var _map2 = _interopRequireDefault(require("lodash/map"));
|
|
9
|
-
var _size2 = _interopRequireDefault(require("lodash/size"));
|
|
10
9
|
var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
|
|
11
10
|
var _fromPairs2 = _interopRequireDefault(require("lodash/fromPairs"));
|
|
12
|
-
var _parseInt2 = _interopRequireDefault(require("lodash/parseInt"));
|
|
13
|
-
var _isString2 = _interopRequireDefault(require("lodash/isString"));
|
|
14
11
|
var _isPlainObject2 = _interopRequireDefault(require("lodash/isPlainObject"));
|
|
15
12
|
var _isInteger2 = _interopRequireDefault(require("lodash/isInteger"));
|
|
16
13
|
var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined"));
|
|
@@ -213,8 +210,8 @@ class EntityManager {
|
|
|
213
210
|
*
|
|
214
211
|
* @callback ShardQueryFunction
|
|
215
212
|
* @param {string} shardedKey - Sharded key.
|
|
216
|
-
* @param {number} [limit] - Request limit.
|
|
217
213
|
* @param {*} [pageKey] - Page key.
|
|
214
|
+
* @param {number} [limit] - Request limit.
|
|
218
215
|
* @returns {Promise<ShardQueryResult>} Sharded query result.
|
|
219
216
|
*/
|
|
220
217
|
|
|
@@ -234,7 +231,7 @@ class EntityManager {
|
|
|
234
231
|
* @param {ShardQueryFunction} options.shardQuery - Sharded query function.
|
|
235
232
|
* @param {number} [options.limit] - Request limit.
|
|
236
233
|
* @param {object} [options.pageKeys] - Map of shard page keys.
|
|
237
|
-
* @param {number
|
|
234
|
+
* @param {number} [options.pageSize] - Request page size.
|
|
238
235
|
* @returns {Promise<ShardedQueryResult>} Sharded query result.
|
|
239
236
|
*/
|
|
240
237
|
async query() {
|
|
@@ -245,7 +242,7 @@ class EntityManager {
|
|
|
245
242
|
shardQuery,
|
|
246
243
|
limit,
|
|
247
244
|
pageKeys,
|
|
248
|
-
|
|
245
|
+
pageSize
|
|
249
246
|
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
250
247
|
// Validate params.
|
|
251
248
|
this.#entityManager.validateKeyToken(entityToken, keyToken);
|
|
@@ -253,13 +250,13 @@ class EntityManager {
|
|
|
253
250
|
if (!(0, _isFunction2.default)(shardQuery)) throw new Error('shardQuery must be a function');
|
|
254
251
|
if (!(0, _isUndefined2.default)(limit) && !((0, _isInteger2.default)(limit) && limit >= 1)) throw new Error('limit must be a positive integer');
|
|
255
252
|
if (!(0, _isUndefined2.default)(pageKeys) && !(0, _isPlainObject2.default)(pageKeys)) throw new Error('pageKeys must be an object');
|
|
256
|
-
if (!(0, _isUndefined2.default)(
|
|
253
|
+
if (!(0, _isUndefined2.default)(pageSize) && !((0, _isInteger2.default)(pageSize) && pageSize >= 1)) throw new Error('pageSize must be a positive integer');
|
|
257
254
|
|
|
258
255
|
// Apply default limit.
|
|
259
256
|
limit ??= this.#entityManager.getEntityConfig(entityToken).defaultLimit;
|
|
260
257
|
|
|
261
|
-
//
|
|
262
|
-
|
|
258
|
+
// Apply default pageSize.
|
|
259
|
+
pageSize ??= this.#entityManager.getEntityConfig(entityToken).defaultPageSize;
|
|
263
260
|
|
|
264
261
|
// Generate default pageKeys if not provided
|
|
265
262
|
pageKeys ??= (0, _fromPairs2.default)(this.getKeySpace(entityToken, keyToken, item).map(shardedKey => [shardedKey, undefined]));
|
|
@@ -270,7 +267,7 @@ class EntityManager {
|
|
|
270
267
|
shardQuery,
|
|
271
268
|
limit,
|
|
272
269
|
pageKeys,
|
|
273
|
-
|
|
270
|
+
pageSize
|
|
274
271
|
});
|
|
275
272
|
|
|
276
273
|
// Return empty result if no pageKeys.
|
|
@@ -280,9 +277,6 @@ class EntityManager {
|
|
|
280
277
|
pageKeys: {}
|
|
281
278
|
};
|
|
282
279
|
|
|
283
|
-
// Calculate shard limit.
|
|
284
|
-
const shardLimit = (0, _isUndefined2.default)(limit) ? undefined : Math.ceil(limit / (0, _size2.default)(pageKeys));
|
|
285
|
-
|
|
286
280
|
// Iterate search over pages.
|
|
287
281
|
let page = 0;
|
|
288
282
|
const result = {
|
|
@@ -291,8 +285,12 @@ class EntityManager {
|
|
|
291
285
|
pageKeys
|
|
292
286
|
};
|
|
293
287
|
do {
|
|
288
|
+
// TODO: This loop will blow up as shards scale, since at a minimum it will return shardCount x pageSize
|
|
289
|
+
// items, which may be >> limit. Probably the way to fix this is to limit the number of shards queried per
|
|
290
|
+
// iteration in order to keep shardsQueried * pageSize > (limit - items.length) but only just.
|
|
291
|
+
|
|
294
292
|
// Query every shard in pageKeys.
|
|
295
|
-
const shardQueryResults = await Promise.all((0, _map2.default)(result.pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey, pageKey,
|
|
293
|
+
const shardQueryResults = await Promise.all((0, _map2.default)(result.pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey, pageKey, pageSize).then(_ref6 => {
|
|
296
294
|
let {
|
|
297
295
|
count,
|
|
298
296
|
items,
|
|
@@ -334,7 +332,7 @@ class EntityManager {
|
|
|
334
332
|
result.items = [...result.items, ...pageResult.items];
|
|
335
333
|
result.pageKeys = pageResult.pageKeys;
|
|
336
334
|
page++;
|
|
337
|
-
} while (
|
|
335
|
+
} while (result.items.length < limit && !(0, _isEmpty2.default)(result.pageKeys));
|
|
338
336
|
return result;
|
|
339
337
|
}
|
|
340
338
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.PrivateEntityManager = exports.DEFAULT_LIMIT = void 0;
|
|
6
|
+
exports.PrivateEntityManager = exports.DEFAULT_PAGE_SIZE = exports.DEFAULT_LIMIT = void 0;
|
|
7
7
|
var _isInteger2 = _interopRequireDefault(require("lodash/isInteger"));
|
|
8
8
|
var _isPlainObject2 = _interopRequireDefault(require("lodash/isPlainObject"));
|
|
9
9
|
var _range2 = _interopRequireDefault(require("lodash/range"));
|
|
@@ -26,7 +26,8 @@ var _mapValues2 = _interopRequireDefault(require("lodash/mapValues"));
|
|
|
26
26
|
var _jsonschema = require("jsonschema");
|
|
27
27
|
var _stringHash = _interopRequireDefault(require("string-hash"));
|
|
28
28
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
29
|
-
const DEFAULT_LIMIT = exports.DEFAULT_LIMIT =
|
|
29
|
+
const DEFAULT_LIMIT = exports.DEFAULT_LIMIT = 10;
|
|
30
|
+
const DEFAULT_PAGE_SIZE = exports.DEFAULT_PAGE_SIZE = 10;
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* EntityManager config validation schema.
|
|
@@ -45,6 +46,9 @@ const configSchema = {
|
|
|
45
46
|
defaultLimit: {
|
|
46
47
|
type: 'integer'
|
|
47
48
|
},
|
|
49
|
+
defaultPageSize: {
|
|
50
|
+
type: 'integer'
|
|
51
|
+
},
|
|
48
52
|
indexes: {
|
|
49
53
|
type: 'object',
|
|
50
54
|
additionalProperties: {
|
|
@@ -175,6 +179,7 @@ class PrivateEntityManager {
|
|
|
175
179
|
entities: (0, _mapValues2.default)(entities, _ref => {
|
|
176
180
|
let {
|
|
177
181
|
defaultLimit = DEFAULT_LIMIT,
|
|
182
|
+
defaultPageSize = DEFAULT_PAGE_SIZE,
|
|
178
183
|
indexes = {},
|
|
179
184
|
keys = {},
|
|
180
185
|
sharding: {
|
|
@@ -187,6 +192,7 @@ class PrivateEntityManager {
|
|
|
187
192
|
} = _ref;
|
|
188
193
|
return {
|
|
189
194
|
defaultLimit,
|
|
195
|
+
defaultPageSize,
|
|
190
196
|
indexes,
|
|
191
197
|
keys,
|
|
192
198
|
sharding: {
|
|
@@ -196,8 +196,8 @@ export class EntityManager {
|
|
|
196
196
|
*
|
|
197
197
|
* @callback ShardQueryFunction
|
|
198
198
|
* @param {string} shardedKey - Sharded key.
|
|
199
|
-
* @param {number} [limit] - Request limit.
|
|
200
199
|
* @param {*} [pageKey] - Page key.
|
|
200
|
+
* @param {number} [limit] - Request limit.
|
|
201
201
|
* @returns {Promise<ShardQueryResult>} Sharded query result.
|
|
202
202
|
*/
|
|
203
203
|
|
|
@@ -217,7 +217,7 @@ export class EntityManager {
|
|
|
217
217
|
* @param {ShardQueryFunction} options.shardQuery - Sharded query function.
|
|
218
218
|
* @param {number} [options.limit] - Request limit.
|
|
219
219
|
* @param {object} [options.pageKeys] - Map of shard page keys.
|
|
220
|
-
* @param {number
|
|
220
|
+
* @param {number} [options.pageSize] - Request page size.
|
|
221
221
|
* @returns {Promise<ShardedQueryResult>} Sharded query result.
|
|
222
222
|
*/
|
|
223
223
|
async query({
|
|
@@ -227,26 +227,30 @@ export class EntityManager {
|
|
|
227
227
|
shardQuery,
|
|
228
228
|
limit,
|
|
229
229
|
pageKeys,
|
|
230
|
-
|
|
230
|
+
pageSize,
|
|
231
231
|
} = {}) {
|
|
232
232
|
// Validate params.
|
|
233
233
|
this.#entityManager.validateKeyToken(entityToken, keyToken);
|
|
234
234
|
this.#entityManager.validateItem(item);
|
|
235
|
+
|
|
235
236
|
if (!_.isFunction(shardQuery))
|
|
236
237
|
throw new Error('shardQuery must be a function');
|
|
238
|
+
|
|
237
239
|
if (!_.isUndefined(limit) && !(_.isInteger(limit) && limit >= 1))
|
|
238
240
|
throw new Error('limit must be a positive integer');
|
|
241
|
+
|
|
239
242
|
if (!_.isUndefined(pageKeys) && !_.isPlainObject(pageKeys))
|
|
240
243
|
throw new Error('pageKeys must be an object');
|
|
241
|
-
|
|
242
|
-
|
|
244
|
+
|
|
245
|
+
if (!_.isUndefined(pageSize) && !(_.isInteger(pageSize) && pageSize >= 1))
|
|
246
|
+
throw new Error('pageSize must be a positive integer');
|
|
243
247
|
|
|
244
248
|
// Apply default limit.
|
|
245
249
|
limit ??= this.#entityManager.getEntityConfig(entityToken).defaultLimit;
|
|
246
250
|
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
251
|
+
// Apply default pageSize.
|
|
252
|
+
pageSize ??=
|
|
253
|
+
this.#entityManager.getEntityConfig(entityToken).defaultPageSize;
|
|
250
254
|
|
|
251
255
|
// Generate default pageKeys if not provided
|
|
252
256
|
pageKeys ??= _.fromPairs(
|
|
@@ -263,29 +267,28 @@ export class EntityManager {
|
|
|
263
267
|
shardQuery,
|
|
264
268
|
limit,
|
|
265
269
|
pageKeys,
|
|
266
|
-
|
|
270
|
+
pageSize,
|
|
267
271
|
});
|
|
268
272
|
|
|
269
273
|
// Return empty result if no pageKeys.
|
|
270
274
|
if (_.isEmpty(pageKeys)) return { count: 0, items: [], pageKeys: {} };
|
|
271
275
|
|
|
272
|
-
// Calculate shard limit.
|
|
273
|
-
const shardLimit = _.isUndefined(limit)
|
|
274
|
-
? undefined
|
|
275
|
-
: Math.ceil(limit / _.size(pageKeys));
|
|
276
|
-
|
|
277
276
|
// Iterate search over pages.
|
|
278
277
|
let page = 0;
|
|
279
278
|
const result = { count: 0, items: [], pageKeys };
|
|
280
279
|
|
|
281
280
|
do {
|
|
281
|
+
// TODO: This loop will blow up as shards scale, since at a minimum it will return shardCount x pageSize
|
|
282
|
+
// items, which may be >> limit. Probably the way to fix this is to limit the number of shards queried per
|
|
283
|
+
// iteration in order to keep shardsQueried * pageSize > (limit - items.length) but only just.
|
|
284
|
+
|
|
282
285
|
// Query every shard in pageKeys.
|
|
283
286
|
const shardQueryResults = await Promise.all(
|
|
284
287
|
_.map(
|
|
285
288
|
result.pageKeys,
|
|
286
289
|
(pageKey, shardedKey) =>
|
|
287
290
|
new Promise((resolve) =>
|
|
288
|
-
shardQuery(shardedKey, pageKey,
|
|
291
|
+
shardQuery(shardedKey, pageKey, pageSize).then(
|
|
289
292
|
({ count, items, pageKey }) =>
|
|
290
293
|
resolve({ count, items, pageKey, shardedKey })
|
|
291
294
|
)
|
|
@@ -315,11 +318,7 @@ export class EntityManager {
|
|
|
315
318
|
result.items = [...result.items, ...pageResult.items];
|
|
316
319
|
result.pageKeys = pageResult.pageKeys;
|
|
317
320
|
page++;
|
|
318
|
-
} while (
|
|
319
|
-
page < pages &&
|
|
320
|
-
result.items.length < limit &&
|
|
321
|
-
!_.isEmpty(result.pageKeys)
|
|
322
|
-
);
|
|
321
|
+
} while (result.items.length < limit && !_.isEmpty(result.pageKeys));
|
|
323
322
|
|
|
324
323
|
return result;
|
|
325
324
|
}
|
|
@@ -2,7 +2,8 @@ import { validate } from 'jsonschema';
|
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import stringHash from 'string-hash';
|
|
4
4
|
|
|
5
|
-
export const DEFAULT_LIMIT =
|
|
5
|
+
export const DEFAULT_LIMIT = 10;
|
|
6
|
+
export const DEFAULT_PAGE_SIZE = 10;
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* EntityManager config validation schema.
|
|
@@ -21,6 +22,9 @@ const configSchema = {
|
|
|
21
22
|
defaultLimit: {
|
|
22
23
|
type: 'integer',
|
|
23
24
|
},
|
|
25
|
+
defaultPageSize: {
|
|
26
|
+
type: 'integer',
|
|
27
|
+
},
|
|
24
28
|
indexes: {
|
|
25
29
|
type: 'object',
|
|
26
30
|
additionalProperties: {
|
|
@@ -141,6 +145,7 @@ export class PrivateEntityManager {
|
|
|
141
145
|
entities,
|
|
142
146
|
({
|
|
143
147
|
defaultLimit = DEFAULT_LIMIT,
|
|
148
|
+
defaultPageSize = DEFAULT_PAGE_SIZE,
|
|
144
149
|
indexes = {},
|
|
145
150
|
keys = {},
|
|
146
151
|
sharding: {
|
|
@@ -152,6 +157,7 @@ export class PrivateEntityManager {
|
|
|
152
157
|
} = {},
|
|
153
158
|
}) => ({
|
|
154
159
|
defaultLimit,
|
|
160
|
+
defaultPageSize,
|
|
155
161
|
indexes,
|
|
156
162
|
keys,
|
|
157
163
|
sharding: {
|