zamza
Version:
Apache Kafka discovery, indexing, searches, storage, hooks and HTTP gateway
135 lines (134 loc) • 4.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Debug = require("debug");
const debug = Debug("zamza:replayhandler");
const uuid = require("uuid");
const MirrorConsumer_1 = require("./kafka/MirrorConsumer");
const MessageHandler_1 = require("./MessageHandler");
class ReplayHandler {
constructor(zamza) {
this.zamza = zamza;
this.instanceId = uuid.v4();
debug("Instance Replay ID:", this.instanceId);
this.replayModel = zamza.mongoWrapper.getReplay();
this.replayProducer = zamza.replayProducer;
this.metrics = zamza.metrics;
this.mirrorConsumer = null;
this.currentTargetTopic = null;
this.currentConsumerGroup = null;
}
createConsumerGroupId() {
return `zamza-internal-mirror-${uuid.v4()}`;
}
async messageHandle(message) {
const replayMessage = {
message,
};
this.metrics.inc("mirrored_messages");
await this.replayProducer.produceMessage(MessageHandler_1.INTERNAL_TOPICS.REPLAY_TOPIC, undefined, undefined, JSON.stringify(replayMessage));
}
isCurrentlyRunning() {
if (this.mirrorConsumer) {
return true;
}
else {
return false;
}
}
dealsWithTopic(topic) {
if (this.currentTargetTopic === topic) {
return true;
}
else {
return false;
}
}
async getCurrentReplay() {
// clean-up
const replayForInstanceId = await this.replayModel.getForInstanceId(this.instanceId);
if (replayForInstanceId && !this.isCurrentlyRunning()) {
await this.replayModel.delete(replayForInstanceId.topic);
}
// clean-up
if (!replayForInstanceId && this.isCurrentlyRunning()) {
await this.replayModel.upsert({
instanceId: this.instanceId,
topic: this.currentTargetTopic,
consumerGroup: this.currentConsumerGroup,
timestamp: Date.now(),
});
}
return {
instanceId: this.instanceId,
replay: await this.replayModel.getForInstanceId(this.instanceId),
};
}
async isBeingReplayedByAnyInstance(topic) {
const replay = await this.replayModel.get(topic);
return !!replay;
}
async flushall() {
debug("Flushing all instances..");
await this.flushone();
await this.replayModel.truncate();
debug("Flushed.");
return true;
}
async flushone() {
debug("Flushing current instance");
if (this.currentTargetTopic) {
await this.replayModel.delete(this.currentTargetTopic);
}
await this.replayModel.deleteForInstanceId(this.instanceId);
if (this.mirrorConsumer) {
await this.mirrorConsumer.close();
}
this.mirrorConsumer = null;
this.currentConsumerGroup = null;
this.currentTargetTopic = null;
debug("Flushed.");
return true;
}
listReplays() {
return this.replayModel.list();
}
async startReplay(topic, consumerGroup) {
if (this.mirrorConsumer) {
throw new Error("Consumer is already running on this instance.");
}
debug("Starting replay..");
const replay = {
instanceId: this.instanceId,
topic,
consumerGroup: consumerGroup ? consumerGroup : this.createConsumerGroupId(),
timestamp: Date.now(),
};
this.currentConsumerGroup = replay.consumerGroup;
this.currentTargetTopic = topic;
await this.replayModel.upsert(replay);
this.mirrorConsumer = new MirrorConsumer_1.default(Object.assign(this.zamza.config.kafka, {
consumer: this.zamza.cloneKafkaConsumerConfig(replay.consumerGroup, this.zamza.config.kafka),
}), this.zamza);
this.mirrorConsumer.start(this.messageHandle.bind(this));
this.mirrorConsumer.adjustSubscriptions([replay.topic]);
return replay;
}
async stopReplay() {
if (!this.mirrorConsumer) {
throw new Error("No consumer running on this instance.");
}
debug("Stopping replay..");
await this.mirrorConsumer.close();
await this.replayModel.delete(this.currentTargetTopic);
this.mirrorConsumer = null;
this.currentTargetTopic = null;
this.currentConsumerGroup = null;
return true;
}
async close() {
if (this.mirrorConsumer) {
await this.mirrorConsumer.close();
}
}
}
exports.ReplayHandler = ReplayHandler;