@restorecommerce/chassis-srv
Version:
Restore Commerce microservice chassis
91 lines • 3.56 kB
JavaScript
import { createClient } from 'redis';
/**
* Stores the offsets of the provided topics to redis periodically
*/
export class OffsetStore {
kafkaEvents;
config;
logger;
redisClient;
// protected readonly topics: Record<string, Topic> = {};
timerID = [];
prefix;
constructor(kafkaEvents, config, logger, redisClient) {
this.kafkaEvents = kafkaEvents;
this.config = config;
this.logger = logger;
this.redisClient = redisClient;
if (!kafkaEvents) {
logger?.error('No Kafka client was provided, offsets will not be stored to redis');
return;
}
if (!this.config.get('events:kafka:topics')) {
throw new Error('Kafka events configuration was not provided.');
}
this.prefix = this.config.get('events:kafka:kafka:clientId');
const redisConfig = this.config.get('redis');
if (!redisClient && redisConfig) {
redisConfig.database = this.config.get('redis:db-indexes:db-offsetStore') ?? 0;
this.redisClient = createClient(redisConfig);
this.redisClient.on('error', (err) => logger?.error('Redis Client error in offsetstore', err));
this.redisClient.connect().then(() => logger?.info('Redis client connection successful for offsetstore'));
}
setTimeout(this.updateTopicOffsets.bind(this), 5000);
}
/**
* updates the topic offset in redis periodically
*
*/
async updateTopicOffsets() {
// Iterate through the topics and updateOffsets periodically for each topic
// events.topic(TopicName) - gives the topic object
const kafkaCfg = this.config.get('events:kafka');
const topicTypes = Object.keys(kafkaCfg.topics ?? {});
for (let i = 0; i < topicTypes.length; i += 1) {
const topicType = topicTypes[i];
const topicName = kafkaCfg.topics[topicType].topic;
this.kafkaEvents.topic(topicName).then(topic => {
// this.topics[topicType] = topic;
this.timerID[i] = setInterval(this.storeOffset.bind(this), this.config.get('redis:offsetStoreInterval') ?? 1000, topic, topicName);
});
}
}
/**
* stores the offset to redis
* @param {object} topic Topic object
* @param {object} redisClient
* @return {object}
*/
async storeOffset(topic, topicName) {
// get the latest offset here each time and store it.
const offsetValue = await topic.$offset(BigInt(-1));
const redisKey = `${this.prefix}:${topicName}`;
this.redisClient.set(redisKey, offsetValue.toString(10));
}
/**
* get the offset value for the topic from redis
* @param {string} topic Topic name
* @return {object}
*/
async getOffset(topicName) {
const redisKey = `${this.prefix}:${topicName}`;
const offsetValue = await this.redisClient.get(redisKey);
this.logger?.info('The offset value retreived from redis for topic is:', { topicName, offsetValue: Number(offsetValue) });
return BigInt(offsetValue || 0);
}
/**
* stops the redis client
* @param {object} topic Topic object
* @param {object} redisClient
* @return {object}
*/
async stop() {
for (let i = 0; i < this.timerID.length; i += 1) {
clearInterval(this.timerID[i]);
}
if (this.redisClient) {
await this.redisClient.quit();
}
}
}
//# sourceMappingURL=index.js.map