From f2a0ce8518ae3082dec2647ce42a52b1c4746933 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Wed, 13 May 2026 18:02:59 -0700 Subject: [PATCH 1/5] [Fix] freestyle-mock honors $PORT, drop server.listen string-patch The multi-worker freestyle-mock rewrite (#1430) hardcoded `server.listen(8080)`, which collides with qstash inside the emulator container (supervisord sets `PORT=8180` for freestyle-mock). The local- emulator Dockerfile previously patched this via a string-replace, but the new source no longer matches the literal pattern, so qstash failed with `address already in use: 127.0.0.1:8080` and the backend never came up. Make the source respect `process.env.PORT` directly and remove the brittle replace. --- docker/dependencies/freestyle-mock/Dockerfile | 5 +++-- docker/local-emulator/Dockerfile | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/dependencies/freestyle-mock/Dockerfile b/docker/dependencies/freestyle-mock/Dockerfile index b378ded8a0..5855d48d6b 100644 --- a/docker/dependencies/freestyle-mock/Dockerfile +++ b/docker/dependencies/freestyle-mock/Dockerfile @@ -380,8 +380,9 @@ const server = createServer(async (req, res) => { } }); -server.listen(8080, () => { - console.log(`freestyle-mock listening on :8080 (worker pool size ${POOL_SIZE})`); +const PORT = process.env.PORT || 8080; +server.listen(PORT, () => { + console.log(`freestyle-mock listening on :${PORT} (worker pool size ${POOL_SIZE})`); }); EOF diff --git a/docker/local-emulator/Dockerfile b/docker/local-emulator/Dockerfile index f08a977a92..2672058d7e 100644 --- a/docker/local-emulator/Dockerfile +++ b/docker/local-emulator/Dockerfile @@ -117,7 +117,6 @@ RUN node -e " \ fs.writeFileSync('package.json', pkgMatch[1]); \ const srvMatch = df.match(/cat <<'EOF' > server\\.mjs\\n([\\s\\S]*?)\\nEOF/); \ let server = srvMatch[1]; \ - server = server.replace('server.listen(8080)', 'server.listen(process.env.PORT || 8080)'); \ server = server.replace( \ 'from \"fs/promises\"', \ 'from \"fs/promises\"; import { symlinkSync } from \"fs\"' \ From 358df4e0734b9dd4d12ed3a84f2d07d020e31427 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Wed, 13 May 2026 18:42:49 -0700 Subject: [PATCH 2/5] [Fix] raise dummy session-activity seed tx timeout to 90s Under cross-arch arm64 TCG in the qemu-emulator-build CI job, the deleteMany + createMany batch for ~1500-2000 event rows has been observed to take 40-50s, exceeding the previously-set 30s Prisma interactive-transaction ceiling (run 25835455849 hit 44.7s). The transaction uses deterministic IDs and is idempotent, so a looser bound has no correctness downside; it only kicks in on the slow TCG path. --- apps/backend/src/lib/seed-dummy-data.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/backend/src/lib/seed-dummy-data.ts b/apps/backend/src/lib/seed-dummy-data.ts index e117402eb7..d70781b7a4 100644 --- a/apps/backend/src/lib/seed-dummy-data.ts +++ b/apps/backend/src/lib/seed-dummy-data.ts @@ -1636,10 +1636,10 @@ async function seedDummySessionActivityEvents(options: SessionActivityEventSeedO }); }, { // Under cross-arch arm64 TCG in the emulator qcow2 build, this batch - // takes ~10s; Prisma's default is 5s. Production (KVM/native) runs it - // in well under 1s, so the looser bound only kicks in when the DB is - // genuinely slow. - timeout: 30_000, + // has been observed to take 40-50s; Prisma's default is 5s. Production + // (KVM/native) runs it in well under 1s, so the looser bound only kicks + // in when the DB is genuinely slow. + timeout: 90_000, }); if (clickhouseClient && clickhouseRows.length > 0) { From b35837075326f5083765c04a53e0126672096e0c Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Wed, 13 May 2026 19:36:44 -0700 Subject: [PATCH 3/5] [Fix] raise emulator Postgres statement_timeout to 300s Under cross-arch arm64 TCG in the qemu-emulator-build CI job, a query in runBulldozerPaymentsInit/paginatedIngress exceeds the 120s server-side statement_timeout, returning Postgres error 57014 (P2010 from Prisma). KVM/native production runs the same query in well under a second; the looser bound only kicks in on the slow emulated path. --- docker/local-emulator/supervisord.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/local-emulator/supervisord.conf b/docker/local-emulator/supervisord.conf index a9d3d51da8..cc21c1ae41 100644 --- a/docker/local-emulator/supervisord.conf +++ b/docker/local-emulator/supervisord.conf @@ -25,7 +25,7 @@ command=/usr/lib/postgresql/16/bin/postgres -c max_connections=500 -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all - -c statement_timeout=120s + -c statement_timeout=300s user=postgres autostart=true autorestart=true From e2759a15fa405412d83e9e303a21f3711805d18c Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Thu, 14 May 2026 09:59:32 -0700 Subject: [PATCH 4/5] [Fix] disable Postgres statement_timeout in local emulator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bulldozer payments-seed cascade is O(N^2) in jsonb work because each setRow propagates through ~65 derived tables and an LFold maintains a per-customer subscription map that grows without bound. Under cross-arch arm64 TCG, even handfuls of seed rows blow past any reasonable statement_timeout — a single OneTimePurchase insert was observed at 304s. This Postgres instance only runs at qcow2-build time; production has its own server with its own timeout policy. Setting statement_timeout=0 here removes the CI flake without touching product behavior. --- docker/local-emulator/supervisord.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/local-emulator/supervisord.conf b/docker/local-emulator/supervisord.conf index cc21c1ae41..cb7dda854f 100644 --- a/docker/local-emulator/supervisord.conf +++ b/docker/local-emulator/supervisord.conf @@ -25,7 +25,7 @@ command=/usr/lib/postgresql/16/bin/postgres -c max_connections=500 -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all - -c statement_timeout=300s + -c statement_timeout=0 user=postgres autostart=true autorestart=true From 159e29daaae6df55bf8033b7f43e881af7e73fe2 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Thu, 14 May 2026 13:35:18 -0700 Subject: [PATCH 5/5] [Fix] enable KVM in smoke-test job so cold boot fits the 600s budget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The smoke-test job has been silently running QEMU under TCG because the runner's /dev/kvm exists but isn't writable by the default user. The CLI's accelerator selection is a single check: `[ -w /dev/kvm ]` → otherwise it falls back to TCG. The build job mirrors this udev rule already and its KVM-accelerated cold boot completes in ~46s. Without KVM, recent dev merges have grown the boot's startup work past the 600s EMULATOR_READY_TIMEOUT under TCG. With KVM, this drops back to under a minute. --- .github/workflows/qemu-emulator-build.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/qemu-emulator-build.yaml b/.github/workflows/qemu-emulator-build.yaml index 5792b7f600..a659368500 100644 --- a/.github/workflows/qemu-emulator-build.yaml +++ b/.github/workflows/qemu-emulator-build.yaml @@ -243,6 +243,19 @@ jobs: echo "/opt/qemu/bin" >> "$GITHUB_PATH" /opt/qemu/bin/qemu-system-x86_64 --version + - name: Enable KVM access + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \ + | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm || true + ls -la /dev/kvm || echo "no /dev/kvm present" + if [ -w /dev/kvm ]; then + echo "KVM is writable — hardware acceleration will be used" + else + echo "WARNING: /dev/kvm is not writable — will fall back to TCG (very slow)" + fi + - uses: pnpm/action-setup@v4 with: version: 10.23.0