chore: change the quota sync to the queue
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import { EntityManager } from "@mikro-orm/core";
|
||||
import { InjectQueue } from "@nestjs/bullmq";
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import { Cron, CronExpression } from "@nestjs/schedule";
|
||||
import { Queue } from "bullmq";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { Business } from "../../businesses/entities/business.entity";
|
||||
import { WildDuckUsersService } from "../../mail-server/services/wildduck-users.service";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { QUOTA_SYNC_QUEUE } from "../constants";
|
||||
import {
|
||||
BusinessQuotaInfoDto,
|
||||
BusinessQuotaStatisticsDto,
|
||||
@@ -14,20 +16,127 @@ import {
|
||||
QuotaSyncResultDto,
|
||||
UserQuotaStatisticsDto,
|
||||
} from "../DTO/quota-statistics.dto";
|
||||
import { ISyncBusinessQuotaJob, ISyncUserQuotaJob } from "../interfaces/quota-sync-job.interface";
|
||||
|
||||
@Injectable()
|
||||
export class QuotaSyncService {
|
||||
private readonly logger = new Logger(QuotaSyncService.name);
|
||||
|
||||
constructor(
|
||||
@InjectQueue(QUOTA_SYNC_QUEUE.QUEUE_NAME) private readonly quotaSyncQueue: Queue,
|
||||
private readonly wildDuckUsersService: WildDuckUsersService,
|
||||
private readonly em: EntityManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Sync quota usage every 2 hours
|
||||
* Add a job to sync quota usage for all users
|
||||
*/
|
||||
async scheduleAllUsersQuotaSync(): Promise<void> {
|
||||
await this.quotaSyncQueue.add(
|
||||
QUOTA_SYNC_QUEUE.SYNC_ALL_USERS_QUOTA_JOB,
|
||||
{},
|
||||
{
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
attempts: 3,
|
||||
backoff: {
|
||||
type: "exponential",
|
||||
delay: 2000,
|
||||
},
|
||||
},
|
||||
);
|
||||
this.logger.log("Scheduled all users quota sync job");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a job to sync business quota usage for all businesses
|
||||
*/
|
||||
async scheduleAllBusinessQuotasSync(): Promise<void> {
|
||||
await this.quotaSyncQueue.add(
|
||||
QUOTA_SYNC_QUEUE.SYNC_ALL_BUSINESSES_QUOTA_JOB,
|
||||
{},
|
||||
{
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
attempts: 3,
|
||||
backoff: {
|
||||
type: "exponential",
|
||||
delay: 2000,
|
||||
},
|
||||
},
|
||||
);
|
||||
this.logger.log("Scheduled all businesses quota sync job");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a job to sync quota for a specific user
|
||||
*/
|
||||
async scheduleUserQuotaSync(userId: string, businessId: string, wildduckUserId: string): Promise<void> {
|
||||
const jobData: ISyncUserQuotaJob = {
|
||||
userId,
|
||||
businessId,
|
||||
wildduckUserId,
|
||||
};
|
||||
|
||||
await this.quotaSyncQueue.add(QUOTA_SYNC_QUEUE.SYNC_USER_QUOTA_JOB, jobData, {
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
attempts: 3,
|
||||
backoff: {
|
||||
type: "exponential",
|
||||
delay: 2000,
|
||||
},
|
||||
});
|
||||
this.logger.log(`Scheduled user quota sync job for user: ${userId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a job to sync quota for a specific business
|
||||
*/
|
||||
async scheduleBusinessQuotaSync(businessId: string, businessName: string): Promise<void> {
|
||||
const jobData: ISyncBusinessQuotaJob = {
|
||||
businessId,
|
||||
businessName,
|
||||
};
|
||||
|
||||
await this.quotaSyncQueue.add(QUOTA_SYNC_QUEUE.SYNC_BUSINESS_QUOTA_JOB, jobData, {
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
attempts: 3,
|
||||
backoff: {
|
||||
type: "exponential",
|
||||
delay: 2000,
|
||||
},
|
||||
});
|
||||
this.logger.log(`Scheduled business quota sync job for business: ${businessName}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a job for comprehensive quota sync
|
||||
*/
|
||||
async scheduleComprehensiveQuotaSync(): Promise<void> {
|
||||
await this.quotaSyncQueue.add(
|
||||
QUOTA_SYNC_QUEUE.SYNC_COMPREHENSIVE_QUOTA_JOB,
|
||||
{},
|
||||
{
|
||||
removeOnComplete: true,
|
||||
removeOnFail: false,
|
||||
attempts: 3,
|
||||
backoff: {
|
||||
type: "exponential",
|
||||
delay: 2000,
|
||||
},
|
||||
},
|
||||
);
|
||||
this.logger.log("Scheduled comprehensive quota sync job");
|
||||
}
|
||||
|
||||
// The following methods remain the same but without cron decorators
|
||||
// They are now called by the queue processor
|
||||
|
||||
/**
|
||||
* Sync quota usage for all users (called by processor)
|
||||
*/
|
||||
@Cron(CronExpression.EVERY_2_HOURS)
|
||||
async syncAllUsersQuota(): Promise<void> {
|
||||
const em = this.em.fork();
|
||||
this.logger.log("Starting quota synchronization for all users");
|
||||
@@ -60,13 +169,13 @@ export class QuotaSyncService {
|
||||
this.logger.log(`Quota sync completed: ${successCount} success, ${errorCount} errors`);
|
||||
} catch (error) {
|
||||
this.logger.error("Failed to sync quota for users", `${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync business quota usage every 4 hours
|
||||
* Sync business quota usage for all businesses (called by processor)
|
||||
*/
|
||||
@Cron(CronExpression.EVERY_4_HOURS)
|
||||
async syncAllBusinessQuotas(): Promise<void> {
|
||||
const em = this.em.fork();
|
||||
this.logger.log("Starting business quota synchronization");
|
||||
@@ -97,6 +206,7 @@ export class QuotaSyncService {
|
||||
this.logger.log(`Business quota sync completed: ${successCount} success, ${errorCount} errors`);
|
||||
} catch (error) {
|
||||
this.logger.error("Failed to sync quota for businesses", `${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user