From 7e640e22e4ff202278fd027849d13b78f6748ba6 Mon Sep 17 00:00:00 2001 From: Yaacov Date: Tue, 8 Sep 2026 19:42:46 +0300 Subject: [PATCH] Enable production desktop analytics ingestion --- scripts/analytics-report.mjs | 44 ++++++++++++++++++------ scripts/analytics-report.test.mjs | 16 ++++++++- workers/events/worker-configuration.d.ts | 6 ++-- workers/events/wrangler.jsonc | 4 +-- 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/scripts/analytics-report.mjs b/scripts/analytics-report.mjs index 15efae1..27b55c4 100644 --- a/scripts/analytics-report.mjs +++ b/scripts/analytics-report.mjs @@ -188,17 +188,41 @@ export const analyticsReportQuery = ` ORDER BY report_section, event_count DESC, item `; +/** Cloudflare D1 limits compound SELECT terms more tightly than local SQLite. */ +export function analyticsReportQueries(maxTerms = 4) { + if (!Number.isInteger(maxTerms) || maxTerms < 2) { + throw new Error("Analytics report chunks require at least two SELECT terms"); + } + const body = analyticsReportQuery + .replace(/\n\s*ORDER BY report_section, event_count DESC, item\s*$/, "") + .trim(); + const terms = body.split(/\n\s*UNION ALL\s*\n/); + const first = terms.shift(); + const maintenance = terms.pop(); + if (!first || !maintenance || !maintenance.includes("analytics_maintenance_status")) { + throw new Error("Analytics report query structure is invalid"); + } + + const chunks = [[first, maintenance]]; + while (terms.length > 0) chunks.push(terms.splice(0, maxTerms)); + return chunks.map( + (chunk) => + `${chunk.join("\n\n UNION ALL\n\n")}\n\n ORDER BY report_section, event_count DESC, item`, + ); +} + // Importing the query for local fixture tests must never contact production. if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { - const result = spawnSync( - "wrangler", - ["d1", "execute", "scientfactory-downloads", "--remote", "--command", analyticsReportQuery], - { stdio: "inherit", timeout: 60_000 }, - ); - if (result.error) { - console.error("Analytics aggregate report failed or timed out"); - process.exitCode = 1; - } else { - process.exitCode = result.status ?? 1; + for (const query of analyticsReportQueries()) { + const result = spawnSync( + "wrangler", + ["d1", "execute", "scientfactory-downloads", "--remote", "--command", query], + { stdio: "inherit", timeout: 60_000 }, + ); + if (result.error || result.status !== 0) { + console.error("Analytics aggregate report failed or timed out"); + process.exitCode = result.status ?? 1; + break; + } } } diff --git a/scripts/analytics-report.test.mjs b/scripts/analytics-report.test.mjs index a19d792..26ca6ea 100644 --- a/scripts/analytics-report.test.mjs +++ b/scripts/analytics-report.test.mjs @@ -1,9 +1,23 @@ import { expect, it } from "vitest"; -import { analyticsReportQuery } from "./analytics-report.mjs"; +import { analyticsReportQueries, analyticsReportQuery } from "./analytics-report.mjs"; import { testDatabase } from "../workers/events/src/sqlite.testSupport.ts"; const fixedQuery = analyticsReportQuery.replaceAll("'now'", "'2026-08-31T12:00:00.000Z'"); +it("keeps remote report chunks within the D1 compound SELECT limit", () => { + const store = testDatabase(); + try { + const queries = analyticsReportQueries(); + expect(queries.length).toBeGreaterThan(1); + for (const query of queries) { + expect(query.match(/\bSELECT\b/g)?.length).toBeLessThanOrEqual(4); + expect(() => store.sqlite.prepare(query).all()).not.toThrow(); + } + } finally { + store.close(); + } +}); + it("reports centrally retained diagnostics separately from PostHog delivery", () => { const store = testDatabase(); try { diff --git a/workers/events/worker-configuration.d.ts b/workers/events/worker-configuration.d.ts index 6e8e387..c600e7d 100644 --- a/workers/events/worker-configuration.d.ts +++ b/workers/events/worker-configuration.d.ts @@ -1,11 +1,11 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types --config=workers/events/wrangler.jsonc --include-runtime=false --env-interface=AnalyticsWorkerBindings workers/events/worker-configuration.d.ts` (hash: ee9d44a6ab6f6fd522cbd77158166bc2) +// Generated by Wrangler by running `wrangler types --config=workers/events/wrangler.jsonc --include-runtime=false --env-interface=AnalyticsWorkerBindings workers/events/worker-configuration.d.ts` (hash: 81f6792a18d83d567c47b9a872304e01) interface __BaseEnv_AnalyticsWorkerBindings { ANALYTICS_DB: D1Database; ANALYTICS_INGESTION_RATE_LIMITER: RateLimit; CF_VERSION_METADATA: WorkerVersionMetadata; - DESKTOP_INGESTION_ENABLED: "false"; - DESKTOP_POSTHOG_EXPORT_ENABLED: "false"; + DESKTOP_INGESTION_ENABLED: "true"; + DESKTOP_POSTHOG_EXPORT_ENABLED: "true"; POSTHOG_PROJECT_ID: "228610"; POSTHOG_PROJECT_TOKEN: string; POSTHOG_PERSONAL_API_KEY: string; diff --git a/workers/events/wrangler.jsonc b/workers/events/wrangler.jsonc index cfe27c9..f2d3895 100644 --- a/workers/events/wrangler.jsonc +++ b/workers/events/wrangler.jsonc @@ -5,8 +5,8 @@ "compatibility_date": "2026-07-20", "compatibility_flags": ["nodejs_compat"], "vars": { - "DESKTOP_INGESTION_ENABLED": "false", - "DESKTOP_POSTHOG_EXPORT_ENABLED": "false", + "DESKTOP_INGESTION_ENABLED": "true", + "DESKTOP_POSTHOG_EXPORT_ENABLED": "true", "POSTHOG_PROJECT_ID": "228610", }, "secrets": {