Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f457fc1
Update dependencies and enhance Cloud Run support
mantrakp04 Apr 2, 2026
5ca107c
Move Dockerfile to docker/backend
N2D4 Apr 2, 2026
490cab6
Add .gcloudignore file to exclude specific files from Google Cloud de…
mantrakp04 Apr 2, 2026
23e760d
Remove .gcloudignore file and simplify Dockerfile installation comman…
mantrakp04 Apr 2, 2026
42747da
Refactor imports to use background-tasks utility
mantrakp04 Apr 2, 2026
ee150a9
Implement OpenTelemetry shutdown handling and enhance database connec…
mantrakp04 Apr 2, 2026
eb0627a
Add E2E Fallback Tests Workflow and Update Environment Configurations
mantrakp04 Apr 3, 2026
6e18155
Refactor fallback URL handling and enhance backend API resilience
mantrakp04 Apr 3, 2026
8cbaae6
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 3, 2026
cd6e7e4
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 3, 2026
0c1cfa8
Refactor OpenTelemetry integration and cleanup
mantrakp04 Apr 3, 2026
a5efcad
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 3, 2026
573f69e
Enhance SDK fallback logic and update test configurations
mantrakp04 Apr 3, 2026
01a6652
Update e2e fallback tests command for improved execution
mantrakp04 Apr 3, 2026
a10b0f1
Update e2e fallback tests command to exclude additional test files
mantrakp04 Apr 3, 2026
a5788ff
Add Cloud Build configuration for Docker image build and deployment
mantrakp04 Apr 3, 2026
41cdf3b
Refine SDK fallback tests command to streamline exclusions
mantrakp04 Apr 3, 2026
f9efe6b
Remove cloudbuild.yaml configuration file for Docker image build and …
mantrakp04 Apr 3, 2026
f45e081
Refactor StackClientInterface for improved URL fallback handling
mantrakp04 Apr 3, 2026
3546663
Refactor prisma-client and background-tasks for improved SIGTERM hand…
mantrakp04 Apr 3, 2026
0640a72
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 6, 2026
50fd34a
Remove unnecessary ESLint disable comment in background-tasks.tsx for…
mantrakp04 Apr 6, 2026
d47d395
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 8, 2026
c6e5b92
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 8, 2026
3228ca2
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 9, 2026
25be3f2
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 9, 2026
e23330a
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 9, 2026
fe1fc15
Merge branch 'dev' into gcp-stuff
mantrakp04 Apr 10, 2026
5d95240
Refactor Cloud Run IP handling in getBrowserEndUserInfo and enhance S…
mantrakp04 Apr 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor prisma-client and background-tasks for improved SIGTERM hand…
…ling

- Reintroduced the ensurePolyfilled function in prisma-client.tsx to ensure environment variables are expanded.
- Simplified the PostgreSQL connection pool setup by removing dynamic pool size configuration, defaulting to a max of 25.
- Enhanced SIGTERM handling to ensure graceful shutdown of background tasks and database connections, with clearer comments for maintainability.
- Updated background-tasks.tsx to clarify the purpose of in-flight promises during shutdown.

These changes improve the reliability and clarity of the database connection management and shutdown process.
  • Loading branch information
mantrakp04 committed Apr 3, 2026
commit 35466635a3a35f4a837156c118a8c8ff688350b2
19 changes: 5 additions & 14 deletions apps/backend/src/prisma-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import { isPromise } from "util/types";
import { runMigrationNeeded } from "./auto-migrations";
import { registerPgPool } from "./lib/dev-perf-stats";
import { Tenancy } from "./lib/tenancies";
import { ensurePolyfilled } from "./polyfills";
import { drainInFlightPromises } from "./utils/background-tasks";
import { ensurePolyfilled } from "./polyfills";

// just ensure we're polyfilled because this file relies on envvars being expanded
ensurePolyfilled();
Expand Down Expand Up @@ -85,13 +85,9 @@ function getPostgresPrismaClient(connectionString: string, poolLabel?: string) {
let postgresPrismaClient = postgresPrismaClientsStore.get(connectionString);
if (!postgresPrismaClient) {
const schema = getSchemaFromConnectionString(connectionString);
const poolMaxRaw = parseInt(getEnvVariable("STACK_DATABASE_POOL_MAX", "25"), 10);
const poolMax = Number.isFinite(poolMaxRaw) && poolMaxRaw > 0 ? poolMaxRaw : 25;
const pool = new Pool({ connectionString, max: poolMax });
pool.on('error', (err) => {
// Prevent unhandled rejections from crashing the process (e.g. on Cloud Run)
captureError("pg-pool-error", err);
});
const pool = new Pool({ connectionString, max: 25 });
// pg Pool emits 'error' on idle clients (e.g. TCP reset); unhandled = process crash
pool.on('error', (err) => captureError("pg-pool-error", err));
registerPgPool(pool, poolLabel ?? connectionString); // Register pool for dev performance stats
const adapter = new PrismaPg(pool, schema ? { schema } : undefined);
postgresPrismaClient = {
Expand All @@ -103,25 +99,20 @@ function getPostgresPrismaClient(connectionString: string, poolLabel?: string) {
return postgresPrismaClient;
}

// Graceful shutdown for non-Vercel runtimes (Cloud Run sends SIGTERM before shutdown)
// Cloud Run sends SIGTERM before shutdown; drain background tasks and close DB connections.
if (!getEnvVariable("VERCEL", "") && !globalVar.__stack_prisma_sigterm_registered) {
globalVar.__stack_prisma_sigterm_registered = true;
process.on("SIGTERM", () => {
// Keep the event loop alive so Node doesn't exit before the drain completes.
// 10s timeout > 8s drain timeout to ensure we have enough time.
const keepAlive = setTimeout(() => {}, 10_000);

runAsynchronously(async () => {
try {
console.log("[SIGTERM] Draining background tasks and database connections...");
await drainInFlightPromises(8000);
for (const [, entry] of postgresPrismaClientsStore) {
await entry.client.$disconnect();
}
for (const [, client] of prismaClientsStore.neon) {
await client.$disconnect();
}
console.log("[SIGTERM] Completed draining background tasks and database connections.");
} finally {
clearTimeout(keepAlive);
}
Comment thread
mantrakp04 marked this conversation as resolved.
Expand Down
5 changes: 1 addition & 4 deletions apps/backend/src/utils/background-tasks.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env";
import { ignoreUnhandledRejection, runAsynchronously } from "@stackframe/stack-shared/dist/utils/promises";

/**
* In-flight background promises tracked for graceful shutdown on non-Vercel runtimes (e.g. Cloud Run).
* On SIGTERM, we drain these before exiting. See SIGTERM handler in prisma-client.tsx.
*/
// Tracked for SIGTERM drain on non-Vercel runtimes (e.g. Cloud Run).
const inFlightPromises = new Set<Promise<unknown>>();

const isVercel = !!getEnvVariable("VERCEL", "");
Expand Down
2 changes: 2 additions & 0 deletions apps/e2e/tests/js/inheritance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { isUuid } from "@stackframe/stack-shared/dist/utils/uuids";
import { STACK_BACKEND_BASE_URL, it } from "../helpers";
import { scaffoldProject } from "./js-helpers";

// When STACK_TEST_SDK_FALLBACK is set, omit explicit baseUrl so the SDK resolves
// from NEXT_PUBLIC_STACK_API_URL and exercises its fallback logic
const sdkBaseUrl = process.env.STACK_TEST_SDK_FALLBACK ? undefined : STACK_BACKEND_BASE_URL;

it("StackServerApp can inherit configuration from StackClientApp", async ({ expect }) => {
Expand Down
Loading