57 lines
1.5 KiB
JavaScript
Executable File
57 lines
1.5 KiB
JavaScript
Executable File
// src/services/push.service.js
|
|
const webpush = require('web-push');
|
|
const config = require('../config');
|
|
const pushRepo = require('../repositories/push.repo');
|
|
|
|
const hasVapid = !!config.vapid.publicKey && !!config.vapid.privateKey;
|
|
|
|
if (!hasVapid) {
|
|
console.warn('[Push] VAPID keys não definidas. Push desativado.');
|
|
} else {
|
|
webpush.setVapidDetails(config.vapid.subject, config.vapid.publicKey, config.vapid.privateKey);
|
|
}
|
|
|
|
async function sendWithRetry(subscription, message, tries = 2) {
|
|
try {
|
|
return await webpush.sendNotification(subscription, message);
|
|
} catch (err) {
|
|
const code = err?.statusCode;
|
|
if ((code === 429 || code >= 500) && tries > 1) {
|
|
await new Promise((r) => setTimeout(r, 1000));
|
|
return sendWithRetry(subscription, message, tries - 1);
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
async function sendPushToUser(userId, payload) {
|
|
if (!hasVapid) return;
|
|
|
|
const subs = await pushRepo.listByUser(userId);
|
|
if (!subs.length) return;
|
|
|
|
const message = JSON.stringify(payload);
|
|
|
|
await Promise.allSettled(
|
|
subs.map(async (s) => {
|
|
const subscription = {
|
|
endpoint: s.endpoint,
|
|
keys: { p256dh: s.p256dh, auth: s.auth },
|
|
};
|
|
|
|
try {
|
|
await sendWithRetry(subscription, message);
|
|
} catch (err) {
|
|
const code = err?.statusCode;
|
|
if (code === 404 || code === 410) {
|
|
await pushRepo.deleteById(s.id);
|
|
} else {
|
|
console.error('[Push] erro ao enviar:', err.message);
|
|
}
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
module.exports = { sendPushToUser };
|