api-v1/jobs/expirationJob.js

68 lines
2.7 KiB
JavaScript

import schedule from "node-cron";
import { insert, execute } from "../db/queryHelper/index.js";
import { getIO, getSocketId } from "../socket.js";
// Run every hour
export const startExpirationJob = () => {
schedule.schedule("0 * * * *", async () => {
console.log("Running listing expiration check...");
try {
const result = await execute({
type: 'transaction',
handler: async (trx) => {
// 1. Identify expired listings (active & not updated in last 48h)
const expiredListings = await trx('listings')
.select('id', 'title', 'seller_id')
.where({ status: 'active', deleted: false })
.whereRaw("updated_at < NOW() - INTERVAL '48 hours'")
.forUpdate()
.skipLocked();
if (expiredListings.length === 0) {
return [];
}
console.log(`Found ${expiredListings.length} listings to expire.`);
// 2. Update status to 'expired'
const expiredIds = expiredListings.map(l => l.id);
await trx('listings')
.whereIn('id', expiredIds)
.update({ status: 'expired' });
// 3. Create Notifications & Real-time Alerts
for (const listing of expiredListings) {
const message = `Your listing "${listing.title}" has expired after 48 hours of inactivity. Click here to re-list it.`;
// Insert Notification
await trx('notifications').insert({
user_id: listing.seller_id,
type: 'listing_expired',
message,
data: { listing_id: listing.id }
});
// Real-time Socket Emit
const socketId = getSocketId(listing.seller_id);
if (socketId) {
getIO().to(socketId).emit("notification", {
type: "listing_expired",
message,
data: { listing_id: listing.id }
});
}
}
return expiredListings;
}
});
if (result && result.length > 0) {
console.log("Expiration check completed successfully.");
}
} catch (err) {
console.error("Error in expiration job:", err);
}
});
};