feat: Implement a generic user timers system with a scheduler to manage cooldowns, effects, and access.

This commit is contained in:
syntaxbullet
2025-12-13 14:18:46 +01:00
parent b33738aee3
commit d34e872133
6 changed files with 194 additions and 30 deletions

View File

@@ -1,4 +1,4 @@
import { users, transactions, cooldowns } from "@/db/schema";
import { users, transactions, userTimers } from "@/db/schema";
import { eq, sql, and } from "drizzle-orm";
import { DrizzleClient } from "@/lib/DrizzleClient";
import { GameConfig } from "@/config/game";
@@ -77,15 +77,16 @@ export const economyService = {
startOfDay.setHours(0, 0, 0, 0);
// Check cooldown
const cooldown = await txFn.query.cooldowns.findFirst({
const cooldown = await txFn.query.userTimers.findFirst({
where: and(
eq(cooldowns.userId, BigInt(userId)),
eq(cooldowns.actionKey, 'daily')
eq(userTimers.userId, BigInt(userId)),
eq(userTimers.type, 'COOLDOWN'),
eq(userTimers.key, 'daily')
),
});
if (cooldown && cooldown.readyAt > now) {
throw new Error(`Daily already claimed. Ready at ${cooldown.readyAt}`);
if (cooldown && cooldown.expiresAt > now) {
throw new Error(`Daily already claimed. Ready at ${cooldown.expiresAt}`);
}
// Get user for streak logic
@@ -101,7 +102,7 @@ export const economyService = {
// If previous cooldown exists and expired more than 24h ago (meaning >48h since last claim), reset streak
if (cooldown) {
const timeSinceReady = now.getTime() - cooldown.readyAt.getTime();
const timeSinceReady = now.getTime() - cooldown.expiresAt.getTime();
if (timeSinceReady > 24 * 60 * 60 * 1000) {
streak = 1;
}
@@ -126,15 +127,16 @@ export const economyService = {
// Set new cooldown (now + 24h)
const nextReadyAt = new Date(now.getTime() + GameConfig.economy.daily.cooldownMs);
await txFn.insert(cooldowns)
await txFn.insert(userTimers)
.values({
userId: BigInt(userId),
actionKey: 'daily',
readyAt: nextReadyAt,
type: 'COOLDOWN',
key: 'daily',
expiresAt: nextReadyAt,
})
.onConflictDoUpdate({
target: [cooldowns.userId, cooldowns.actionKey],
set: { readyAt: nextReadyAt },
target: [userTimers.userId, userTimers.type, userTimers.key],
set: { expiresAt: nextReadyAt },
});
// Log Transaction