|
|
|
|
@ -415,6 +415,15 @@ export const ResponseQueue = {
|
|
|
|
|
updated_at = strftime('%Y-%m-%d %H:%M:%f', 'now')
|
|
|
|
|
WHERE id = ?
|
|
|
|
|
`).run(statusCode ?? null, id);
|
|
|
|
|
// Recalcular métricas agregadas de onboarding si aplica
|
|
|
|
|
try {
|
|
|
|
|
const row = this.dbInstance.prepare(`SELECT metadata FROM response_queue WHERE id = ?`).get(id) as any;
|
|
|
|
|
let meta: any = null;
|
|
|
|
|
try { meta = row?.metadata ? JSON.parse(String(row.metadata)) : null; } catch {}
|
|
|
|
|
if (meta && meta.kind === 'onboarding') {
|
|
|
|
|
this.setOnboardingAggregatesMetrics();
|
|
|
|
|
}
|
|
|
|
|
} catch {}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
markFailed(id: number, errorMsg: string, statusCode?: number, attempts?: number) {
|
|
|
|
|
@ -444,6 +453,50 @@ export const ResponseQueue = {
|
|
|
|
|
`).run(nextAttempts, nextAttemptAt, msg, statusCode ?? null, id);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
setOnboardingAggregatesMetrics(): void {
|
|
|
|
|
try {
|
|
|
|
|
// Total de mensajes de onboarding enviados
|
|
|
|
|
const sentRow = this.dbInstance.prepare(`
|
|
|
|
|
SELECT COUNT(*) AS c
|
|
|
|
|
FROM response_queue
|
|
|
|
|
WHERE status = 'sent' AND metadata LIKE '%"kind":"onboarding"%'
|
|
|
|
|
`).get() as any;
|
|
|
|
|
const sentAbs = Number(sentRow?.c || 0);
|
|
|
|
|
|
|
|
|
|
// Destinatarios únicos con al menos 1 onboarding enviado
|
|
|
|
|
const rcptRow = this.dbInstance.prepare(`
|
|
|
|
|
SELECT COUNT(DISTINCT recipient) AS c
|
|
|
|
|
FROM response_queue
|
|
|
|
|
WHERE status = 'sent' AND metadata LIKE '%"kind":"onboarding"%'
|
|
|
|
|
`).get() as any;
|
|
|
|
|
const recipientsAbs = Number(rcptRow?.c || 0);
|
|
|
|
|
|
|
|
|
|
// Usuarios convertidos: last_command_at > primer onboarding enviado
|
|
|
|
|
const convRow = this.dbInstance.prepare(`
|
|
|
|
|
SELECT COUNT(*) AS c
|
|
|
|
|
FROM users u
|
|
|
|
|
JOIN (
|
|
|
|
|
SELECT recipient, MIN(created_at) AS first_at
|
|
|
|
|
FROM response_queue
|
|
|
|
|
WHERE status = 'sent' AND metadata LIKE '%"kind":"onboarding"%'
|
|
|
|
|
GROUP BY recipient
|
|
|
|
|
) f ON f.recipient = u.id
|
|
|
|
|
WHERE u.last_command_at IS NOT NULL
|
|
|
|
|
AND u.last_command_at > f.first_at
|
|
|
|
|
`).get() as any;
|
|
|
|
|
const convertedAbs = Number(convRow?.c || 0);
|
|
|
|
|
|
|
|
|
|
const rate = recipientsAbs > 0 ? Math.max(0, Math.min(1, convertedAbs / recipientsAbs)) : 0;
|
|
|
|
|
|
|
|
|
|
try { Metrics.set('onboarding_dm_sent_abs', sentAbs); } catch {}
|
|
|
|
|
try { Metrics.set('onboarding_recipients_abs', recipientsAbs); } catch {}
|
|
|
|
|
try { Metrics.set('onboarding_converted_users_abs', convertedAbs); } catch {}
|
|
|
|
|
try { Metrics.set('onboarding_conversion_rate', rate); } catch {}
|
|
|
|
|
} catch {
|
|
|
|
|
// no-op
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async workerLoop(workerId: number) {
|
|
|
|
|
while (this._running) {
|
|
|
|
|
try {
|
|
|
|
|
|