Skip to content

Commit 71486a9

Browse files
d-csTrigger.dev RepoOps
authored andcommitted
feat(webapp): make the snapshot store completed-state TTL configurable
The snapshot store's completed-state retention is now configurable with RUN_ENGINE_SNAPSHOT_STORE_COMPLETED_TTL_MS (default 4 days). Mono-RevId: 5d229fefab916dfc1e608023ffb36a512e72b6db
1 parent ff7f091 commit 71486a9

4 files changed

Lines changed: 40 additions & 3 deletions

File tree

‎apps/webapp/app/env.server.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,13 @@ const EnvironmentSchema = z
14591459
RUN_ENGINE_SNAPSHOT_STORE_REDIS_URL: z.string().optional(),
14601460
// How long a fetched org snapshotStoreMode override is reused per process. 0 disables caching.
14611461
RUN_ENGINE_SNAPSHOT_STORE_DIAL_CACHE_MS: z.coerce.number().int().min(0).default(5000),
1462+
// How long a finished run's snapshot state stays in the store. Redis-primary runs fail closed
1463+
// after it expires.
1464+
RUN_ENGINE_SNAPSHOT_STORE_COMPLETED_TTL_MS: z.coerce
1465+
.number()
1466+
.int()
1467+
.positive()
1468+
.default(4 * 24 * 60 * 60 * 1_000),
14621469
// Background sweep that resolves snapshot units left pending by an interrupted transition
14631470
// (see snapshotRecoveryWorker.server.ts). Inert without RUN_ENGINE_SNAPSHOT_STORE_REDIS_URL.
14641471
// Off unless set to "1": enable it on one background replica. Several replicas with it on are

‎apps/webapp/app/v3/runStore.server.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ export const snapshotStoreRuntime = singleton("SnapshotStoreRuntime", () => {
219219
const metrics = createSnapshotStoreMetrics(metricsRegister);
220220
const connection = createSnapshotConnection(endpoint, {
221221
metrics: metrics.store,
222+
completedTtlMs: env.RUN_ENGINE_SNAPSHOT_STORE_COMPLETED_TTL_MS,
222223
onError: (error) => logger.error("Snapshot connection error", { error }),
223224
});
224225
return createSnapshotStoreRuntime({

‎apps/webapp/app/v3/utils/snapshotStoreConnection.server.ts‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { createRedisClusterClient, type Cluster } from "@internal/redis";
22
import { RedisSnapshotStore, type SnapshotStoreMetrics } from "@internal/run-store";
33

4+
const DEFAULT_COMPLETED_TTL_MS = 4 * 24 * 60 * 60 * 1_000;
45
const COMMAND_TIMEOUT_MS = 1_000;
56
const CONNECT_TIMEOUT_MS = 500;
67
const POLICY_CHECK_INTERVAL_MS = 30_000;
7-
const COMPLETED_TTL_MS = 4 * 24 * 60 * 60 * 1_000;
88

99
/** Infrastructure only. Rollout modes belong to the existing polled flags, not this URL. */
1010
export function snapshotClusterOptions(endpoint: string) {
@@ -45,7 +45,12 @@ export function snapshotClusterOptions(endpoint: string) {
4545
*/
4646
export function createSnapshotConnection(
4747
endpoint: string,
48-
options: { metrics?: SnapshotStoreMetrics; onError?: (error: Error) => void } = {}
48+
options: {
49+
metrics?: SnapshotStoreMetrics;
50+
onError?: (error: Error) => void;
51+
/** How long a finished run's snapshot state stays in the store. */
52+
completedTtlMs?: number;
53+
} = {}
4954
) {
5055
const clientOptions = snapshotClusterOptions(endpoint);
5156
let client: Cluster | undefined;
@@ -114,7 +119,7 @@ export function createSnapshotConnection(
114119
getStore: () =>
115120
(store ??= new RedisSnapshotStore({
116121
client: getClient(),
117-
completedTtlMs: COMPLETED_TTL_MS,
122+
completedTtlMs: options.completedTtlMs ?? DEFAULT_COMPLETED_TTL_MS,
118123
beforeCommand,
119124
metrics: options.metrics,
120125
})),

‎apps/webapp/test/env.server.test.ts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,28 @@ describe("webapp environment secrets", () => {
115115
expect(env.GITHUB_APP_CLIENT_ID).toBe("client-id");
116116
expect(env.GITHUB_APP_CLIENT_SECRET).toBe("client-secret");
117117
});
118+
119+
it("defaults the snapshot store completed-state TTL to 4 days", async () => {
120+
process.env = { ...requiredEnv };
121+
122+
const { env } = await import("../app/env.server");
123+
124+
expect(env.RUN_ENGINE_SNAPSHOT_STORE_COMPLETED_TTL_MS).toBe(4 * 24 * 60 * 60 * 1_000);
125+
});
126+
127+
it("reads the snapshot store completed-state TTL from the environment", async () => {
128+
process.env = { ...requiredEnv, RUN_ENGINE_SNAPSHOT_STORE_COMPLETED_TTL_MS: "3600000" };
129+
130+
const { env } = await import("../app/env.server");
131+
132+
expect(env.RUN_ENGINE_SNAPSHOT_STORE_COMPLETED_TTL_MS).toBe(3_600_000);
133+
});
134+
135+
it("rejects a non-positive snapshot store completed-state TTL", async () => {
136+
process.env = { ...requiredEnv, RUN_ENGINE_SNAPSHOT_STORE_COMPLETED_TTL_MS: "0" };
137+
138+
await expect(import("../app/env.server")).rejects.toThrow(
139+
"RUN_ENGINE_SNAPSHOT_STORE_COMPLETED_TTL_MS"
140+
);
141+
});
118142
});

0 commit comments

Comments
 (0)