UNPKG

@fabric-es/fabric-cqrs

Version:

Hyperledger Fabric middleware for event sourcing and cqrs pattern

130 lines 6.87 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createRedisRepository = void 0; const util_1 = __importDefault(require("util")); const debug_1 = __importDefault(require("debug")); const startsWith_1 = __importDefault(require("lodash/startsWith")); const reselect_1 = require("reselect"); const utils_1 = require("../utils"); const model_1 = require("./model"); const pipelineExec_1 = require("./pipelineExec"); const baseIndexDefinition_1 = require("./types/baseIndexDefinition"); const baseSelectors_1 = require("./types/baseSelectors"); const createRedisRepository = (entity, { client, kind = 'entity', fields, param, preSelector, postSelector }) => { const debug = debug_1.default('queryHandler:createRedisRepository'); const entityName = typeof entity === 'string' ? entity : entity.entityName; const logger = utils_1.getLogger({ name: '[query-handler] createRedisRepository.js', target: 'console' }); const indexName = { entity: `eidx:${entityName}`, commit: 'cidx' }[kind]; const prefix = { entity: `e:${entityName}:`, commit: 'c:' }[kind]; const combinedPreSelector = preSelector ? { entity: reselect_1.createSelector(preSelector, baseSelectors_1.basePreSelector, (pre, bse) => (Object.assign(Object.assign({}, pre), bse))), commit: preSelector, }[kind] : undefined; const combinedPostSelector = postSelector ? { entity: reselect_1.createSelector(postSelector, baseSelectors_1.basePostSelector, (pre, bse) => (Object.assign(Object.assign({}, pre), bse))), commit: postSelector, }[kind] : undefined; const combinedFields = { entity: Object.assign(Object.assign({}, fields), baseIndexDefinition_1.baseIndexDefinition), commit: fields, }[kind]; const getKey = { entity: ({ id }) => (!id ? null : `${prefix}${id}`), commit: ({ entityName, entityId, commitId }) => !entityName || !entityId || !commitId ? null : `${prefix}${entityName}:${entityId}:${commitId}`, }[kind]; const getParam = (param) => Object.assign({}, { prefix: [{ count: 1, name: prefix }] }, param); const getSchema = (input) => Object.entries(input) .map(([key, { altName, index }]) => index && Object.assign(Object.assign({}, index), { name: altName !== null && altName !== void 0 ? altName : key })) .filter((item) => !!item); return { createIndex: () => client.create(indexName, getSchema(combinedFields), getParam(param)), deleteItemsByPattern: async (pattern) => { try { return await pipelineExec_1.pipelineExec(client, 'DELETE', pattern).then((data) => [ data.map(([err, _]) => err), data.map(([_, count]) => count).reduce((pre, cur) => pre + cur, 0), ]); } catch (e) { logger.error(util_1.default.format('fail to deleteCommitsByPattern, %j', e)); return [e, null]; } }, dropIndex: (deleteHash = true) => client.dropindex(indexName, deleteHash), hmset: (item, history) => { debug('hmset:item, %O', item); const key = getKey(item); debug('hmset:key, %s', key); if (!key) throw new Error('invalid key'); return client.redis.hmset(key, (combinedPreSelector === null || combinedPreSelector === void 0 ? void 0 : combinedPreSelector([item, history])) || item); }, hgetall: (key) => client.redis .hgetall(key) .then((result) => ((combinedPostSelector === null || combinedPostSelector === void 0 ? void 0 : combinedPostSelector(result)) || result)), getKey: (item) => getKey(item), getIndexName: () => indexName, getPattern: (pattern, args) => ({ COMMITS_BY_ENTITYNAME: `c:${args[0]}:*`, COMMITS_BY_ENTITYNAME_ENTITYID: `c:${args[0]}:${args[1]}:*`, ENTITIES_BY_ENTITYNAME: `e:${args[0]}:*`, ENTITIES_BY_ENTITYNAME_ENTITYID: `e:${args[0]}:${args[1]}:*`, }[pattern]), getPreSelector: () => combinedPreSelector, getPostSelector: () => combinedPostSelector, queryCommitsByPattern: async (pattern) => { try { debug('queryCommitsByPattern:pattern, %s', pattern); return await pipelineExec_1.pipelineExec(client, 'HGETALL', pattern).then((data) => [ data.map(([err, _]) => { debug('queryCommitsByPattern:error, %O', err); return err; }), data .map(([_, commit]) => { debug('queryCommitsByPattern:commit, %O', commit); return model_1.postSelector(commit); }) .sort((a, b) => a.ts - b.ts), ]); } catch (e) { logger.error(util_1.default.format('fail to queryCommitsByPattern, %j', e)); return [e, null]; } }, search: async ({ countTotalOnly, kind, index, query, param, restoreFn }) => { try { const customParm = countTotalOnly ? Object.assign(Object.assign({}, param), { limit: { first: 0, num: 0 } }) : kind === 'commit' ? Object.assign(Object.assign({}, param), { sortBy: { sort: 'ASC', field: 'ts' } }) : param; const data = await client.search(index, query, customParm); const prefix = { commit: 'c:', entity: 'e:' }[kind]; const keys = data.slice(1).filter((item) => startsWith_1.default(item, prefix)); const count = countTotalOnly ? data[0] : keys === null || keys === void 0 ? void 0 : keys.length; if (countTotalOnly) return [[], count, null]; return await pipelineExec_1.pipelineExec(client, 'HGETALL', null, keys).then((data) => [ data.map(([err, _]) => err), count, data.map(([_, item]) => { var _a, _b; return (((_b = (_a = { commit: model_1.postSelector, entity: restoreFn })[kind]) === null || _b === void 0 ? void 0 : _b.call(_a, item)) || item); }), ]); } catch (e) { logger.error(util_1.default.format('fail to search, %j', e)); return [[e], null, null]; } }, }; }; exports.createRedisRepository = createRedisRepository; //# sourceMappingURL=createRedisRepository.js.map