Ir al contenido

Cron jobs

Las tareas programadas están en Google Cloud Scheduler (project api-cards-prod, region us-central1). Cada job hace POST a un endpoint del Cloud Run autenticado con X-Internal-Cron-Secret.

Panelhttps://console.cloud.google.com/cloudscheduler?project=api-cards-prod
Listargcloud scheduler jobs list --project=api-cards-prod --location=us-central1
Pausar unogcloud scheduler jobs pause <name> --project=... --location=...
Forzar ejecución manualgcloud scheduler jobs run <name> --project=... --location=...
Frecuencia0 * * * * (cada hora)
Qué haceDispara backup de Mongo Atlas via API
Endpointexterno (Atlas API), no es de tcgcards-api
RPO efectivo~1 hora
RunbookVer runbook restore
Frecuencia0 * * * * (cada hora)
EndpointPOST /api/v1/internal/cron/orders-tick
Códigosrc/cron/orderTickService.ts
Qué hace4 sub-tareas (ver abajo)
IdempotenteSí — re-procesar es seguro

Sub-tareas que ejecuta:

Sub-tareaTriggerAcción
processPendingOrden creada hace >72h, vendedor no aceptóAuto-cancela + restaura stock + mail
processAcceptedOrden aceptada hace >168h (7 días), no se envióAuto-cancela + restaura stock + mail
processShippedOrden enviada hace >336h (14 días), buyer no confirmóAuto-completa (libera pago al vendedor) + mail
processExpiredSuspensionsUsuario con suspendedUntil vencidoDesuspende automáticamente

Warning de 24h antes: para cada deadline, manda email “se cancelará/recibirá en ~24h” cuando faltan menos de 24h.

Frecuencia*/5 * * * * (cada 5 min)
EndpointPOST /api/v1/internal/cron/orders-awaiting-payment-cleanup
Códigosrc/cron/awaitingPaymentCleanupService.ts
Qué haceCancela órdenes en awaiting_payment cuyo paymentTimeoutAt ya pasó (30 min por defecto). Restaura stock. Manda mail de timeout.
Idempotente
Índice clave{status:1, paymentTimeoutAt:1} en orders (agregado 2026-05-20)

También maneja orphan pending orders: órdenes que quedaron en estado pending sin paymentId por crash del proceso entre create() y updateById(). Las cancela si llevan >60 min.

Frecuencia0 3 * * * (diario 3am UTC)
EndpointPOST /api/v1/internal/cron/wallet-reconcile
Códigosrc/cron/walletReconcile.tsReconcileService.reconcileAll()
Qué haceReconcilia user.walletBalance (denormalizado) contra la suma del ledger wallet_entries. Loguea ERROR si encuentra divergencias.
IdempotenteSí (read-only)

Si encuentra una divergencia, escribe log estructurado [wallet-reconcile] DIVERGENCES DETECTED que debe disparar alerta en Sentry. La acción de corrección es manual (endpoint /admin/reconcile o intervención de un dev).

Frecuencia0 4 * * * (diario 4am UTC)
EndpointPOST /api/v1/internal/cron/refunds-reconcile
Códigosrc/payments/services/RefundReconcileService.ts
Qué haceDetecta órdenes canceladas con paymentId cuyo refund no se procesó correctamente. Log ERROR si encuentra inconsistencias.
IdempotenteSí (read-only)
Ventana de terminal
gcloud scheduler jobs update http <job-name> \
--schedule="*/10 * * * *" \
--project=api-cards-prod \
--location=us-central1

Cambia el schedule (cron expression). Las request a la API no cambian; solo el timing.

Ventana de terminal
gcloud scheduler jobs create http nuevo-cron \
--project=api-cards-prod \
--location=us-central1 \
--schedule="0 * * * *" \
--time-zone="UTC" \
--uri="https://tcgcards-api-1033181994095.us-central1.run.app/api/v1/internal/cron/nuevo-cron" \
--http-method=POST \
--oidc-service-account-email=mongo-backup-scheduler@api-cards-prod.iam.gserviceaccount.com \
--headers="X-Internal-Cron-Secret=<valor del secret>"

(Antes de crear, hay que implementar el endpoint en el código + redeploy.)

Detallado en la conversación de 2026-05-20:

JobEstado actualPunto de quiebre
orders-awaiting-payment-cleanupOK con índice nuevo~1.000 órdenes vencidas simultáneas
orders-tickOK pero usa findActiveByStatus() que trae todo a memoria~5.000 órdenes activas (RAM + tiempo)
wallet-reconcile-dailyOK~50.000 usuarios con wallet (depende de Cloud Run timeout)
refunds-reconcile-dailyOKsin riesgo previsible
mongo-backup-hourlyOKsin riesgo (no depende de nuestro código)

Si lo notamos crecer a esos volúmenes hay fixes preparados — ver decisiones técnicas para detalles.