feat: Add automatic periodic location requests via silent push
- Server sends silent push notifications every 60s (configurable) - Only requests from rooms with active participants - Cleans up stale push subscriptions automatically - Interval configurable via LOCATION_REQUEST_INTERVAL env var 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
27e8344e7a
commit
ca1cd4877d
|
|
@ -9,6 +9,8 @@ services:
|
|||
- VAPID_PUBLIC_KEY=BNWACJudUOeHEZKEFB-0Wz086nHYsWzj12LqQ7lsUNT38ThtNUoZTJYEH9lttQitCROE2G3Ob71ZUww47yvCDbk
|
||||
- VAPID_PRIVATE_KEY=${VAPID_PRIVATE_KEY:-x3yCse1Q4rbZ1XLgnJ1KpSuRlw2ccHDW0fMcKtQ1qcw}
|
||||
- VAPID_SUBJECT=mailto:push@rmaps.online
|
||||
# Automatic location request interval (ms) - 0 to disable
|
||||
- LOCATION_REQUEST_INTERVAL=60000
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# HTTP router (redirects to HTTPS via Cloudflare)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import webpush from 'web-push';
|
|||
|
||||
const PORT = process.env.PORT || 3001;
|
||||
const STALE_THRESHOLD_MS = 60 * 60 * 1000; // 1 hour
|
||||
const LOCATION_REQUEST_INTERVAL_MS = parseInt(process.env.LOCATION_REQUEST_INTERVAL || '60000', 10); // 60 seconds default
|
||||
|
||||
// VAPID keys for push notifications
|
||||
// Generate with: npx web-push generate-vapid-keys
|
||||
|
|
@ -292,6 +293,51 @@ setInterval(() => {
|
|||
}
|
||||
}, 5 * 60 * 1000); // Every 5 minutes
|
||||
|
||||
// Automatic location request - periodically ask all clients for location updates via silent push
|
||||
async function requestLocationFromAllRooms() {
|
||||
if (!VAPID_PUBLIC_KEY || !VAPID_PRIVATE_KEY) return;
|
||||
|
||||
for (const [roomSlug, subs] of pushSubscriptions.entries()) {
|
||||
if (subs.size === 0) continue;
|
||||
|
||||
const room = rooms.get(roomSlug);
|
||||
// Only request if room has participants (active room)
|
||||
if (!room || Object.keys(room.participants).length === 0) continue;
|
||||
|
||||
console.log(`[${roomSlug}] Requesting location from ${subs.size} subscribers`);
|
||||
|
||||
const failedEndpoints = [];
|
||||
for (const sub of subs) {
|
||||
try {
|
||||
await webpush.sendNotification(sub, JSON.stringify({
|
||||
silent: true,
|
||||
data: { type: 'location_request', roomSlug }
|
||||
}));
|
||||
} catch (error) {
|
||||
if (error.statusCode === 404 || error.statusCode === 410) {
|
||||
failedEndpoints.push(sub.endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up failed subscriptions
|
||||
for (const endpoint of failedEndpoints) {
|
||||
for (const sub of subs) {
|
||||
if (sub.endpoint === endpoint) {
|
||||
subs.delete(sub);
|
||||
console.log(`[${roomSlug}] Removed stale push subscription`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start automatic location request interval
|
||||
if (VAPID_PUBLIC_KEY && VAPID_PRIVATE_KEY && LOCATION_REQUEST_INTERVAL_MS > 0) {
|
||||
setInterval(requestLocationFromAllRooms, LOCATION_REQUEST_INTERVAL_MS);
|
||||
console.log(`Automatic location requests enabled every ${LOCATION_REQUEST_INTERVAL_MS / 1000}s`);
|
||||
}
|
||||
|
||||
// Parse JSON body from request
|
||||
async function parseJsonBody(req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue