|
|
| import Redis from 'ioredis'; |
| import { logger } from '../logger'; |
| import { getCachedOrganization } from './organization'; |
|
|
| export class UsageService { |
| |
| |
| |
| |
| 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}`; |
|
|
| |
| const current = await redis.incrby(key, amount); |
| |
| if (current <= amount) { |
| |
| 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<number> { |
| const today = new Date().toISOString().split('T')[0]; |
| const key = `usage:${organizationId}:${today}`; |
| const val = await redis.get(key); |
| return val ? parseInt(val) : 0; |
| } |
| } |
|
|