- Add migration 0004: partial unique index on user_points (user_id, action, recording_id) for RECORDING_CREATE and RECORDING_FEATURED to prevent earn-on-republish farming - Add revokePoints() to gamification lib; awardPoints() now uses onConflictDoNothing - Add gamificationQueue (BullMQ) with 3-attempt exponential backoff - Add gamification worker handling awardPoints, revokePoints, checkAchievements jobs - Move all inline gamification calls in recordings + comments resolvers to queue - Revoke RECORDING_CREATE points when a recording is unpublished (published → draft) - Register gamification worker at server startup alongside mail worker Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
26 lines
808 B
TypeScript
26 lines
808 B
TypeScript
import { Queue } from "bullmq";
|
|
import { redisConnectionOpts } from "./connection.js";
|
|
import { logger } from "../lib/logger.js";
|
|
|
|
const log = logger.child({ component: "queues" });
|
|
|
|
export const mailQueue = new Queue("mail", { connection: redisConnectionOpts });
|
|
mailQueue.on("error", (err) => {
|
|
log.error({ queue: "mail", err: err.message }, "Queue error");
|
|
});
|
|
|
|
export const gamificationQueue = new Queue("gamification", {
|
|
connection: redisConnectionOpts,
|
|
defaultJobOptions: { attempts: 3, backoff: { type: "exponential", delay: 2000 } },
|
|
});
|
|
gamificationQueue.on("error", (err) => {
|
|
log.error({ queue: "gamification", err: err.message }, "Queue error");
|
|
});
|
|
|
|
log.info("Queues initialized");
|
|
|
|
export const queues: Record<string, Queue> = {
|
|
mail: mailQueue,
|
|
gamification: gamificationQueue,
|
|
};
|