import Redis from 'ioredis'; import { logger } from '../logger'; import { getCachedOrganization } from './organization'; export class UsageService { /** * Checks if an organization has exceeded its daily message limit. * Increments the count if within limits. */ static async checkAndIncrement(organizationId: string, redis: Redis, amount: number = 1): Promise<{ allowed: boolean; current: number; limit: number }> { const org = await getCachedOrganization(organizationId); if (!org) return { allowed: false, current: 0, limit: 0 }; const limit = org.dailyMessageLimit || 250; const today = new Date().toISOString().split('T')[0]; const key = `usage:${organizationId}:${today}`; // Atomic increment by amount const current = await redis.incrby(key, amount); if (current <= amount) { // Set expiry for 24h on first use of the day await redis.expire(key, 86400); } if (current > limit) { logger.warn(`[USAGE] Org ${organizationId} reached limit: ${current}/${limit}`); return { allowed: false, current, limit }; } return { allowed: true, current, limit }; } static async getCurrentUsage(organizationId: string, redis: Redis): Promise { const today = new Date().toISOString().split('T')[0]; const key = `usage:${organizationId}:${today}`; const val = await redis.get(key); return val ? parseInt(val) : 0; } }