feat: aggregate dashboard metrics server-side

This commit is contained in:
Esdras Renan 2025-11-17 13:48:59 -03:00
parent c3ee23f967
commit 3b0484a9ad
4 changed files with 641 additions and 198 deletions

View file

@ -3,12 +3,17 @@ import { api } from "./_generated/api"
const crons = cronJobs() const crons = cronJobs()
crons.interval( // Keep the handler available but only register it when explicitly enabled in Convex env.
"report-export-runner", const reportsCronEnabled = process.env.REPORTS_CRON_ENABLED === "true"
{ minutes: 15 },
api.reports.triggerScheduledExports, if (reportsCronEnabled) {
{} crons.interval(
) "report-export-runner",
{ minutes: 15 },
api.reports.triggerScheduledExports,
{}
)
}
crons.daily( crons.daily(
"auto-pause-internal-lunch", "auto-pause-internal-lunch",

File diff suppressed because it is too large Load diff

View file

@ -726,4 +726,21 @@ export default defineSchema({
.index("by_tenant_company", ["tenantId", "companyId"]) .index("by_tenant_company", ["tenantId", "companyId"])
.index("by_tenant_default", ["tenantId", "isDefault"]) .index("by_tenant_default", ["tenantId", "isDefault"])
.index("by_tenant", ["tenantId"]), .index("by_tenant", ["tenantId"]),
analyticsCache: defineTable({
tenantId: v.string(),
cacheKey: v.string(),
payload: v.any(),
expiresAt: v.number(),
_ttl: v.optional(v.number()),
})
.index("by_key", ["tenantId", "cacheKey"]),
analyticsLocks: defineTable({
tenantId: v.string(),
cacheKey: v.string(),
expiresAt: v.number(),
_ttl: v.optional(v.number()),
})
.index("by_key", ["tenantId", "cacheKey"]),
}); });

View file

@ -26,6 +26,8 @@ services:
NEXT_PUBLIC_APP_URL: "${NEXT_PUBLIC_APP_URL}" NEXT_PUBLIC_APP_URL: "${NEXT_PUBLIC_APP_URL}"
BETTER_AUTH_URL: "${BETTER_AUTH_URL}" BETTER_AUTH_URL: "${BETTER_AUTH_URL}"
BETTER_AUTH_SECRET: "${BETTER_AUTH_SECRET}" BETTER_AUTH_SECRET: "${BETTER_AUTH_SECRET}"
REPORTS_CRON_SECRET: "${REPORTS_CRON_SECRET}"
REPORTS_CRON_BASE_URL: "${REPORTS_CRON_BASE_URL}"
# Mantém o SQLite fora do repositório # Mantém o SQLite fora do repositório
DATABASE_URL: "file:/app/data/db.sqlite" DATABASE_URL: "file:/app/data/db.sqlite"
# Usado para forçar novo rollout a cada deploy (setado pelo CI) # Usado para forçar novo rollout a cada deploy (setado pelo CI)
@ -76,6 +78,9 @@ services:
- MACHINE_PROVISIONING_SECRET=${MACHINE_PROVISIONING_SECRET} - MACHINE_PROVISIONING_SECRET=${MACHINE_PROVISIONING_SECRET}
- MACHINE_TOKEN_TTL_MS=${MACHINE_TOKEN_TTL_MS:-2592000000} - MACHINE_TOKEN_TTL_MS=${MACHINE_TOKEN_TTL_MS:-2592000000}
- FLEET_SYNC_SECRET=${FLEET_SYNC_SECRET:-} - FLEET_SYNC_SECRET=${FLEET_SYNC_SECRET:-}
- REPORTS_CRON_SECRET=${REPORTS_CRON_SECRET}
- REPORTS_CRON_BASE_URL=${REPORTS_CRON_BASE_URL}
- REPORTS_CRON_ENABLED=${REPORTS_CRON_ENABLED:-false}
deploy: deploy:
mode: replicated mode: replicated
replicas: 1 replicas: 1
@ -85,8 +90,9 @@ services:
failure_action: rollback failure_action: rollback
resources: resources:
limits: limits:
# Convex vinha sendo finalizado por OOM (ExitCode 137) com limite de 5G. # Limite conservador para evitar que o backend afete o host inteiro.
# Aumentamos para 6G para aproveitar melhor os 8G da VPS sem mudar a infra. memory: "12G"
reservations:
memory: "6G" memory: "6G"
restart_policy: restart_policy:
condition: any condition: any
@ -105,10 +111,10 @@ services:
- traefik_public - traefik_public
healthcheck: healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:3210/version >/dev/null || exit 1"] test: ["CMD-SHELL", "curl -sf http://localhost:3210/version >/dev/null || exit 1"]
interval: 10s interval: 30s
timeout: 10s timeout: 10s
retries: 5 retries: 10
start_period: 20s start_period: 120s
convex_dashboard: convex_dashboard:
image: ghcr.io/get-convex/convex-dashboard:latest image: ghcr.io/get-convex/convex-dashboard:latest