gg
This commit is contained in:
@@ -1,12 +1,28 @@
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import { Cron } from "@nestjs/schedule";
|
||||
import { PrismaService } from "../database/prisma.service";
|
||||
import {
|
||||
FINISHED_STATE_VALUES_FOR_DB,
|
||||
FINISHED_STATUS_VALUES_FOR_DB,
|
||||
LIVE_STATE_VALUES_FOR_DB,
|
||||
LIVE_STATUS_VALUES_FOR_DB,
|
||||
} from "../common/utils/match-status.util";
|
||||
import {
|
||||
getDateOnlyValueForTimeZone,
|
||||
getShiftedDateStringInTimeZone,
|
||||
getDayBoundsForTimeZone,
|
||||
} from "../common/utils/timezone.util";
|
||||
import { TaskLockService } from "./task-lock.service";
|
||||
|
||||
@Injectable()
|
||||
export class LimitResetterTask {
|
||||
private readonly logger = new Logger(LimitResetterTask.name);
|
||||
private readonly timeZone = "Europe/Istanbul";
|
||||
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly taskLock: TaskLockService,
|
||||
) {}
|
||||
|
||||
private shouldSkipInHistoricalMode(jobName: string): boolean {
|
||||
if (process.env.FEEDER_MODE === "historical") {
|
||||
@@ -22,34 +38,39 @@ export class LimitResetterTask {
|
||||
@Cron("0 3 * * *", { timeZone: "Europe/Istanbul" })
|
||||
async resetUsageLimits() {
|
||||
if (this.shouldSkipInHistoricalMode("resetUsageLimits")) return;
|
||||
this.logger.log("Starting daily usage limit reset job...");
|
||||
await this.taskLock.runWithLease(
|
||||
"resetUsageLimits",
|
||||
30 * 60 * 1000,
|
||||
async () => {
|
||||
this.logger.log("Starting daily usage limit reset job...");
|
||||
|
||||
try {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
try {
|
||||
const today = getDateOnlyValueForTimeZone(this.timeZone);
|
||||
|
||||
// Reset all limits that were last reset before today
|
||||
const result = await this.prisma.usageLimit.updateMany({
|
||||
where: {
|
||||
lastResetDate: { lt: today },
|
||||
},
|
||||
data: {
|
||||
analysisCount: 0,
|
||||
couponCount: 0,
|
||||
lastResetDate: today,
|
||||
},
|
||||
});
|
||||
const result = await this.prisma.usageLimit.updateMany({
|
||||
where: {
|
||||
lastResetDate: { lt: today },
|
||||
},
|
||||
data: {
|
||||
analysisCount: 0,
|
||||
couponCount: 0,
|
||||
lastResetDate: today,
|
||||
},
|
||||
});
|
||||
|
||||
if (result.count > 0) {
|
||||
this.logger.log(
|
||||
`Usage limits for ${result.count} users have been reset`,
|
||||
);
|
||||
} else {
|
||||
this.logger.log("No user limits needed resetting");
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Limit reset job failed: ${error.message}`);
|
||||
}
|
||||
if (result.count > 0) {
|
||||
this.logger.log(
|
||||
`Usage limits for ${result.count} users have been reset`,
|
||||
);
|
||||
} else {
|
||||
this.logger.log("No user limits needed resetting");
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Limit reset job failed: ${error.message}`);
|
||||
}
|
||||
},
|
||||
this.logger,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,37 +79,65 @@ export class LimitResetterTask {
|
||||
@Cron("0 4 * * *", { timeZone: "Europe/Istanbul" })
|
||||
async cleanupOldData() {
|
||||
if (this.shouldSkipInHistoricalMode("cleanupOldData")) return;
|
||||
this.logger.log("Starting data cleanup job...");
|
||||
await this.taskLock.runWithLease(
|
||||
"cleanupOldData",
|
||||
60 * 60 * 1000,
|
||||
async () => {
|
||||
this.logger.log("Starting data cleanup job...");
|
||||
|
||||
try {
|
||||
const thirtyDaysAgo = new Date();
|
||||
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
|
||||
try {
|
||||
const thirtyDaysAgo = new Date();
|
||||
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
|
||||
|
||||
// Delete old AI prediction logs
|
||||
const deletedLogs = await this.prisma.aiPredictionsLog.deleteMany({
|
||||
where: {
|
||||
createdAt: { lt: thirtyDaysAgo },
|
||||
},
|
||||
});
|
||||
const deletedLogs = await this.prisma.aiPredictionsLog.deleteMany({
|
||||
where: {
|
||||
createdAt: { lt: thirtyDaysAgo },
|
||||
},
|
||||
});
|
||||
|
||||
// Delete old live matches (finished more than 1 day ago)
|
||||
// Historical data is already persisted in the 'matches' table
|
||||
const oneDayAgo = new Date();
|
||||
oneDayAgo.setDate(oneDayAgo.getDate() - 1);
|
||||
const yesterdayDate = getShiftedDateStringInTimeZone(
|
||||
-1,
|
||||
this.timeZone,
|
||||
);
|
||||
const { startMs: yesterdayStartMs } = getDayBoundsForTimeZone(
|
||||
yesterdayDate,
|
||||
this.timeZone,
|
||||
);
|
||||
const liveMatchCutoff = new Date(yesterdayStartMs);
|
||||
|
||||
const deletedLiveMatches = await this.prisma.liveMatch.deleteMany({
|
||||
where: {
|
||||
state: "Finished",
|
||||
updatedAt: { lt: oneDayAgo },
|
||||
},
|
||||
});
|
||||
const deletedLiveMatches = await this.prisma.liveMatch.deleteMany({
|
||||
where: {
|
||||
updatedAt: { lt: liveMatchCutoff },
|
||||
OR: [
|
||||
{ status: { in: FINISHED_STATUS_VALUES_FOR_DB } },
|
||||
{ state: { in: FINISHED_STATE_VALUES_FOR_DB } },
|
||||
{
|
||||
AND: [
|
||||
{ scoreHome: { not: null } },
|
||||
{ scoreAway: { not: null } },
|
||||
{
|
||||
NOT: {
|
||||
OR: [
|
||||
{ status: { in: LIVE_STATUS_VALUES_FOR_DB } },
|
||||
{ state: { in: LIVE_STATE_VALUES_FOR_DB } },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Cleanup complete: ${deletedLogs.count} old logs, ${deletedLiveMatches.count} old live matches`,
|
||||
);
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Cleanup job failed: ${error.message}`);
|
||||
}
|
||||
this.logger.log(
|
||||
`Cleanup complete: ${deletedLogs.count} old logs, ${deletedLiveMatches.count} old live matches`,
|
||||
);
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Cleanup job failed: ${error.message}`);
|
||||
}
|
||||
},
|
||||
this.logger,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,26 +146,33 @@ export class LimitResetterTask {
|
||||
@Cron("0 0 * * *", { timeZone: "Europe/Istanbul" })
|
||||
async checkSubscriptions() {
|
||||
if (this.shouldSkipInHistoricalMode("checkSubscriptions")) return;
|
||||
this.logger.log("Checking expired subscriptions...");
|
||||
await this.taskLock.runWithLease(
|
||||
"checkSubscriptions",
|
||||
30 * 60 * 1000,
|
||||
async () => {
|
||||
this.logger.log("Checking expired subscriptions...");
|
||||
|
||||
try {
|
||||
const now = new Date();
|
||||
try {
|
||||
const now = new Date();
|
||||
|
||||
const result = await this.prisma.user.updateMany({
|
||||
where: {
|
||||
subscriptionStatus: "active",
|
||||
subscriptionExpiresAt: { lt: now },
|
||||
},
|
||||
data: {
|
||||
subscriptionStatus: "expired",
|
||||
},
|
||||
});
|
||||
const result = await this.prisma.user.updateMany({
|
||||
where: {
|
||||
subscriptionStatus: "active",
|
||||
subscriptionExpiresAt: { lt: now },
|
||||
},
|
||||
data: {
|
||||
subscriptionStatus: "expired",
|
||||
},
|
||||
});
|
||||
|
||||
if (result.count > 0) {
|
||||
this.logger.log(`${result.count} subscriptions marked as expired`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Subscription check failed: ${error.message}`);
|
||||
}
|
||||
if (result.count > 0) {
|
||||
this.logger.log(`${result.count} subscriptions marked as expired`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Subscription check failed: ${error.message}`);
|
||||
}
|
||||
},
|
||||
this.logger,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user