UNPKG

@defikitdotnet/x-ai-combat

Version:

XCombatAI - Social Media Engagement Template for the Agent Framework

144 lines 5.32 kB
import Redis from 'ioredis'; import { log, warn, error } from '../utils/logger'; export class RedisService { constructor(agentId) { this.redisKeyPrefix = `xai:${agentId}:botresponder:`; log(`RedisService: Using key prefix: ${this.redisKeyPrefix}`); const redisUrl = process.env.REDIS_URL; if (!redisUrl) { throw new Error('REDIS_URL is not defined in environment variables'); } this.client = new Redis(redisUrl); // Kết nối trực tiếp bằng URL this.client.on('error', (err) => error('Redis Client Error:', err)); this.client.on('connect', () => log('RedisService: Connected to Redis')); } // --- Key Getters --- get repliedTweetsKey() { return `${this.redisKeyPrefix}repliedTweets`; } get replyQueueKey() { return `${this.redisKeyPrefix}replyQueue`; } get lastCheckTimeKey() { return `${this.redisKeyPrefix}lastCheckTime`; } get lastProcessingTweetIdKey() { return `${this.redisKeyPrefix}lastProcessingTweetId`; } // --- Connection Management --- async ping() { return this.client.ping(); } async quit() { try { await this.client.quit(); log("RedisService: Connection closed."); } catch (err) { error("RedisService: Error closing connection:", err); } } // --- Replied Tweets Set Operations --- async isTweetReplied(tweetId) { const result = await this.client.sismember(this.repliedTweetsKey, tweetId); return result === 1; } async addRepliedTweet(tweetId) { return this.client.sadd(this.repliedTweetsKey, tweetId); } async addRepliedTweets(tweetIds) { if (tweetIds.length === 0) return 0; return this.client.sadd(this.repliedTweetsKey, ...tweetIds); } async getRepliedTweetCount() { return this.client.scard(this.repliedTweetsKey); } // --- Reply Queue List Operations --- async addToReplyQueue(reply) { return this.client.lpush(this.replyQueueKey, JSON.stringify(reply)); } async getReplyQueue() { const itemsStr = await this.client.lrange(this.replyQueueKey, 0, -1); return itemsStr.map(itemStr => JSON.parse(itemStr)); } async clearReplyQueue() { return this.client.del(this.replyQueueKey); } /** * Remove the first item from the reply queue * @returns Number of items removed (0 or 1) */ async removeFromReplyQueue() { const result = await this.client.lpop(this.replyQueueKey); return result ? 1 : 0; } async requeueFailedReplies(replies) { if (replies.length === 0) return 0; const payloads = replies.map(reply => JSON.stringify(reply)); return this.client.rpush(this.replyQueueKey, ...payloads); } // --- Last Check Time Operations --- async setLastCheckTime(time) { return this.client.set(this.lastCheckTimeKey, time.toISOString()); } async getLastCheckTime() { const storedTime = await this.client.get(this.lastCheckTimeKey); if (storedTime) { const parsedTime = new Date(storedTime); if (!isNaN(parsedTime.getTime())) { return parsedTime; } else { warn(`RedisService: Invalid date format found for key ${this.lastCheckTimeKey}: ${storedTime}`); return null; } } return null; } // --- Last Processing Tweet ID Operations --- async setLastProcessingTweetId(tweetId) { return this.client.set(this.lastProcessingTweetIdKey, tweetId); } async getLastProcessingTweetId() { return this.client.get(this.lastProcessingTweetIdKey); } async clearLastProcessingTweetId() { return this.client.del(this.lastProcessingTweetIdKey); } // --- Leaderboard Cache Operations --- getLeaderboardKey(period, limit, agentId) { const agentSuffix = agentId ? `:${agentId}` : ''; return `${this.redisKeyPrefix}leaderboard:${period}:${limit}${agentSuffix}`; } async cacheLeaderboard(period, limit, data, agentId) { const key = this.getLeaderboardKey(period, limit, agentId); const serializedData = JSON.stringify(data); return this.client.setex(key, 300, serializedData); // TTL: 5 minutes (300 seconds) } async getCachedLeaderboard(period, limit, agentId) { const key = this.getLeaderboardKey(period, limit, agentId); const cachedData = await this.client.get(key); if (cachedData) { try { return JSON.parse(cachedData); } catch (err) { error(`RedisService: Error parsing cached leaderboard data: ${err}`); return null; } } return null; } // --- Expose keys for logging if needed outside --- getKeys() { return { repliedTweetsKey: this.repliedTweetsKey, replyQueueKey: this.replyQueueKey, lastCheckTimeKey: this.lastCheckTimeKey, lastProcessingTweetIdKey: this.lastProcessingTweetIdKey }; } } //# sourceMappingURL=redis-service.js.map