UNPKG

multiconsumer-queue

Version:
167 lines 5.24 kB
"use strict"; /* * Copyright (c) 2017 by The MultiConsumer Queue Project Developers. * Some rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); const immutable_1 = require("immutable"); /** * QueueTopic constructor * @constructor */ function QueueTopic(topic) { return topic; } exports.QueueTopic = QueueTopic; /** * ConsumerGroupId constructor * @constructor */ function ConsumerGroupId(groupId) { return groupId; } exports.ConsumerGroupId = ConsumerGroupId; /** * Wraps a {@Link NamedQueue} with given name, exposing {@Link Queue} interface */ class NamedQueueWrap { constructor(_topic, _out) { this._topic = _topic; this._out = _out; } add(data) { this._out.add(this._topic, data); } process(fn, n) { this._out.process(this._topic, fn, n); } } exports.NamedQueueWrap = NamedQueueWrap; /** * Passes calls to out {@Link NamedQueue} but transforming input topic name using given map function */ class DynamicallyNamedQueue { constructor(topic, out) { this.topic = topic; this.out = out; } add(topic, data) { this.out.add(this.topic(topic), data); } process(topic, fn, n) { this.out.process(this.topic(topic), fn, n); } } exports.DynamicallyNamedQueue = DynamicallyNamedQueue; /** * {@Link MultiConsumerQueue} implementation helper * * Dispatches messages from source Queue to out {@Link NamedQueue} using all group IDs * (syncronized using a RedisLiveSet) as topic names */ class MultiConsumerQueueImpl { /** * @param _source queue to add and dispatch messages from * @param _out a named queue to attach final processors to using groupId as topic name * @param _groups live set to synchronize consumer groups across nodes * @param _jobDataLens lens to extract data from Job, to support multiple implementations */ constructor(_source, _out, _groups, _jobDataLens, _lastGroupsSet = immutable_1.Set()) { this._source = _source; this._out = _out; this._groups = _groups; this._jobDataLens = _jobDataLens; this._lastGroupsSet = _lastGroupsSet; /** * Subscribe for consumer group ids changes */ this._groups.subscribe((consumers) => { this._lastGroupsSet = consumers; }); // subscribe source processing once groups initialized this._groups.onMembersInit(() => { // group members list initialized (loaded from db), can now process source jobs this._source.process((job, cb) => { /** * Dispatch messages from source {@Link Queue} to out {@Link NamedQueue} using ConsumerGroupId as QueueTopic */ this._lastGroupsSet.forEach((groupId) => { if (groupId) { this._out.add(QueueTopic(groupId), this._jobDataLens(job)); } }); cb(); }); }); } /** * Create new job * @param {Object} data * @returns {Job} */ add(data) { this._source.add(data); } /** * Subscribe for processing using given groupId * * All subscribers using same groupId will split messages processing * @param {ConsumerGroupId} groupId * @param {ProcessCallback<Job>} fn * @param {number} n */ process(groupId, fn, n) { /** * Register new consumer group so sources can dispatch messages for new group */ this._groups.add(groupId); /** * Attach handler itself for processing */ this._out.process(QueueTopic(groupId), fn, n); } /** * Removes consumer group for current topic * Use this for cleanup, replace process(groupId) with removeGroup(groupId), deploy for a while */ removeGroup(groupId) { this._groups.remove(groupId); return this; } } exports.MultiConsumerQueueImpl = MultiConsumerQueueImpl; /** * EventBus implementation */ class EventBusImpl { /** * @param _buildQueue MultiConsumerQueue builder function */ constructor(_buildQueue) { this._buildQueue = _buildQueue; this._queueMap = immutable_1.Map(); } topic(topic) { /** * Create queue for given topic name and store the reference */ if (!this._queueMap.has(topic)) { this._queueMap = this._queueMap.set(topic, this._buildQueue(topic)); } return this._queueMap.get(topic); } } exports.EventBusImpl = EventBusImpl; //# sourceMappingURL=index.js.map