Die Zeitberechnung wird nach der ersten Ausführung in Vercel "durchgeführt"JavaScript

Javascript-Forum
Anonymous
 Die Zeitberechnung wird nach der ersten Ausführung in Vercel "durchgeführt"

Post by Anonymous »

Ich begegne ein Problem mit meinem Web -Push -Benachrichtigungssystem, wenn ich es für Vercel bereitstellt. Die Zeit wird nach der ersten Ausführung "durchgeführt" und aktualisiert nicht korrekt, wenn die Funktion erneut ausgelöst wird. Nach der ersten Ausführung nutzt die Funktion jedoch die gleiche Zeit wie beim ersten Laufen. Dieses Problem tritt erst nach der Bereitstellung der App für Vercel auf. Lokal, die Zeitaktualisierungen wie erwartet.

Code: Select all

import { NextResponse } from "next/server";
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 });
}
}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post