@fabric-es/fabric-cqrs
Version:
Hyperledger Fabric middleware for event sourcing and cqrs pattern
130 lines • 6.87 kB
JavaScript
;
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