Das Datum gibt den gleichen Wert über mehrere Anforderungen zurück, wenn sie an Vercel bereitgestellt werden (Next.js RoJavaScript

Javascript-Forum
Anonymous
 Das Datum gibt den gleichen Wert über mehrere Anforderungen zurück, wenn sie an Vercel bereitgestellt werden (Next.js Ro

Post by Anonymous »

Ich benutze eine NEXT.JS App Router API -Route (App/API/Benachrichtigung/Route.TS), um die aktuelle Zeit (in Brasilienzeitzone) zu überprüfen und Benachrichtigungen auszulösen, wenn eine geplante Zeit erreicht ist. Nachfolgende Anforderungen geben den gleichen Zeitstempel zurück (gefrorene Zeit aus der ersten Ausführung), obwohl ich im Handler ein neues Datum () verwende. Anfrage. PrettyPrint-Override ">import connectMongo from "@/libs/mongoose";
import Routine from "@/models/Routine";
import User from "@/models/User";
import PushSubscription from "@/models/PushSubscription";
const webPush = require("web-push");

const vapidPublicKey = process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY;
const vapidPrivateKey = process.env.WEB_PUSH_PRIVATE_KEY;

if (!vapidPublicKey || !vapidPrivateKey) {
throw new Error("VAPID keys not configured");
}

console.log("VAPID keys configured correctly");
webPush.setVapidDetails("mailto:your.email@example.com", vapidPublicKey, vapidPrivateKey);

const getBrazilDateTime = () => {
const now = new Date();
const brazilTime = new Date(now.getTime() - 3 * 60 * 60 * 1000); // adjust for Brazil timezone
return brazilTime;
};

const getDayNameInPortuguese = (date) => {
const days = ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"];
return days[date.getDay()];
};

const getTaskStartTime = (task, currentDay) => {
if (task.dailySchedule instanceof Map && task.dailySchedule.has(currentDay)) {
const daySchedule = task.dailySchedule.get(currentDay);
if (daySchedule && daySchedule.startTime) return daySchedule.startTime;
} else if (task.dailySchedule && typeof task.dailySchedule === "object" && task.dailySchedule[currentDay]?.startTime) {
return task.dailySchedule[currentDay].startTime;
}
if (task.startTime) return task.startTime;
return null;
};

const deduplicateSubscriptions = (subscriptions) => {
const uniqueEndpoints = new Set();
return subscriptions.filter((sub) => {
if (uniqueEndpoints.has(sub.endpoint)) return false;
uniqueEndpoints.add(sub.endpoint);
return true;
});
};

const notifiedTasksCache = new Map();

const isTaskAlreadyNotified = (taskId, userId) => {
const key = `${taskId}-${userId}`;
const lastNotified = notifiedTasksCache.get(key);
if (!lastNotified) return false;
const tenMinutesAgo = Date.now() - 10 * 60 * 1000;
return lastNotified > tenMinutesAgo;
};

const markTaskAsNotified = (taskId, userId) => {
const key = `${taskId}-${userId}`;
notifiedTasksCache.set(key, Date.now());
};

export async function GET(request) {
const headers = new Headers({
"Cache-Control": "no-store, max-age=0, must-revalidate",
"Content-Type": "application/json",
});

const logs = [];
const addLog = (message) => {
console.log(message);
logs.push(`[${new Date().toISOString()}] ${message}`);
};

addLog("🔔 Starting notification check...");
addLog(`🕒 Start timestamp: ${Date.now()}`);

try {
addLog("Connecting to MongoDB...");
await connectMongo();
addLog("MongoDB connection established");

// Update the time on each cycle to ensure the time is current.
const spDate = getBrazilDateTime();
const currentDay = getDayNameInPortuguese(spDate);
const currentTime = spDate.toLocaleTimeString("pt-BR", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
});

addLog(`📅 Brazil date and time: ${spDate.toLocaleString("pt-BR")}`);
addLog(`📅 Day of the week: ${currentDay}`);
addLog(`⏰ Current time: ${currentTime}`);

const users = await User.find({ activeRoutine: { $exists: true, $ne: null } });
addLog(`👥 Found ${users.length} users with active routines`);

if (!users.length) return NextResponse.json({ message: "No users with active routines found." });

const routineIds = users.map((user) => user.activeRoutine).filter(Boolean);
const routines = await Routine.find({ _id: { $in: routineIds } });
const routineMap = new Map();
routines.forEach((routine) => routineMap.set(routine._id.toString(), routine));

let notificationsSent = 0;
let usersNotified = 0;
let duplicatesSkipped = 0;

await Promise.all(
users.map(async (user) => {
const routineId = user.activeRoutine?.toString();
if (!routineId) return;
const routine = routineMap.get(routineId);
if (!routine) return;

const matchingTasks = routine.tasks.filter((task) => {
const taskDays = task.days || [];
const includesDay = taskDays.includes(currentDay);
const taskStartTime = getTaskStartTime(task, currentDay);
return includesDay && taskStartTime === currentTime;
});

if (!matchingTasks.length) return;

for (const matchingTask of matchingTasks) {
if (isTaskAlreadyNotified(matchingTask._id.toString(), user._id.toString())) {
duplicatesSkipped++;
continue;
}

let subscriptions = await PushSubscription.find({ userId: user._id });
if (!subscriptions.length) continue;

subscriptions = deduplicateSubscriptions(subscriptions);
addLog(` 📱 User ${user.email} has ${subscriptions.length} unique devices`);

const payload = JSON.stringify({
title: `🔔 ${matchingTask.name} - Time to start!`,
body: `⏰ ${currentTime} - ${matchingTask.details || "Stay focused on your routine!"}`,
icon: "/icon512_rounded.png",
badge: "/icon192_rounded.png",
tag: `task-${matchingTask._id}`,
data: {
url: `/dashboard/r/${routine._id}`,
taskId: matchingTask._id.toString(),
type: "task-reminder",
timestamp: new Date().toISOString(),
},
actions: [
{ action: "open", title: "📋 View Details" },
{ action: "dismiss", title: "✔️ Got it" },
],
vibrate: [200, 100, 200],
requireInteraction: true,
});

await Promise.all(
subscriptions.map(async (subscription) => {
try {
await webPush.sendNotification(
{
endpoint: subscription.endpoint,
keys: subscription.keys,
},
payload
);
notificationsSent++;
markTaskAsNotified(matchingTask._id.toString(), user._id.toString());
} catch (error) {
if (error.statusCode === 410) {
await PushSubscription.deleteOne({ _id: subscription._id });
}
}
})
);
usersNotified++;
}
})
);

return NextResponse.json(
{
message: `Notifications sent successfully!`,
notificationsSent,
usersNotified,
duplicatesSkipped,
logs,
},
{ headers }
);
} catch (error) {
console.error("Error sending notifications:", error);
return NextResponse.json({ error: "Error processing notifications.", logs }, { status: 500, headers });
}
}
< /code>
🔍 Was ich ausprobiert habe:
Die gesamte externe Logik entfernt - minimaler Handler oben reproduziert das Problem immer noch. Ein bekanntes Problem mit Vercels Funktion Caching oder Cold Start -Verhalten im nächsten.js App -Router?
Wie kann ich sicherstellen>

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post