@silverwind/ioredis-mock
Version:
This library emulates ioredis by performing all operations in-memory.
85 lines (68 loc) • 2.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.xread = xread;
var _promiseContainer = _interopRequireDefault(require("../promise-container"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function xread(option, ...args) {
const Promise = _promiseContainer.default.get();
const {
op,
opVal,
rest
} = option === 'STREAMS' ? {
op: 'COUNT',
opVal: Infinity,
rest: args
} : {
op: option,
opVal: parseInt(args[0], 10),
rest: args.slice(2)
};
if (['COUNT', 'BLOCK'].indexOf(op) < 0) {
throw new Error('ERR syntax error');
}
if (rest.length % 2 !== 0) {
throw new Error("ERR Unbalanced XREAD list of streams: for each stream key an ID or '$' must be specified.");
} // Turn ["stream1", "stream2", "id1", "id2"] into tuples of
// [["stream1", "id1"], ["stream2", "id2"]]
const toPoll = rest.reduce((memo, arg, i) => {
const chunk = Math.floor(i / 2);
const tuple = memo[chunk] || []; // eslint-disable-next-line no-param-reassign
memo[chunk] = tuple.concat(arg);
return memo;
}, []);
const pollStream = (stream, id, count = 1) => {
const data = this.data.get(stream);
if (!data) return [];
return data.reduce((memo, [eventId, ...row]) => {
const {
polled
} = this.data.get(`stream:${stream}:${eventId}`);
if (!polled && (id === '$' || eventId >= id) && memo.length < count) {
this.data.set(`stream:${stream}:${eventId}`, {
polled: true
});
return memo.concat([[eventId, ...row]]);
}
return memo;
}, []);
};
const pollEvents = (streams, countVal) => streams.reduce((memo, [stream, id]) => [[stream, pollStream(stream, id, countVal)]].concat(memo), []);
return op === 'BLOCK' ? new Promise(resolve => {
let timeElapsed = 0;
const f = () => setTimeout(() => {
if (opVal > 0 && timeElapsed < opVal) return resolve(null);
const events = pollEvents(toPoll, 1);
if (events.length > 0) return resolve(events);
timeElapsed += 100;
return f();
}, 100);
f();
}) : new Promise(resolve => {
const events = pollEvents(toPoll, opVal);
if (events.length === 0) return resolve(null);
return resolve(events.slice().reverse());
});
}