Harden dev startup and web typecheck

This commit is contained in:
dirtydishes 2025-12-27 21:20:22 -05:00
parent a94baa745c
commit f2f12f2ebe
4 changed files with 65 additions and 5 deletions

View file

@ -24,6 +24,7 @@
".next/types/**/*.ts" ".next/types/**/*.ts"
], ],
"exclude": [ "exclude": [
"node_modules" "node_modules",
"scripts"
] ]
} }

View file

@ -71,6 +71,7 @@
"@islandflow/bus": "workspace:*", "@islandflow/bus": "workspace:*",
"@islandflow/config": "workspace:*", "@islandflow/config": "workspace:*",
"@islandflow/observability": "workspace:*", "@islandflow/observability": "workspace:*",
"@islandflow/storage": "workspace:*",
"@islandflow/types": "workspace:*", "@islandflow/types": "workspace:*",
"zod": "^3.23.8", "zod": "^3.23.8",
}, },

View file

@ -39,6 +39,33 @@ const envSchema = z.object({
const env = readEnv(envSchema); const env = readEnv(envSchema);
const retry = async <T>(
label: string,
attempts: number,
delayMs: number,
task: () => Promise<T>
): Promise<T> => {
let lastError: unknown;
for (let attempt = 1; attempt <= attempts; attempt += 1) {
try {
return await task();
} catch (error) {
lastError = error;
logger.warn(`${label} attempt failed`, {
attempt,
error: error instanceof Error ? error.message : String(error)
});
if (attempt < attempts) {
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
}
}
throw lastError ?? new Error(`${label} failed after retries`);
};
const limitSchema = z.coerce.number().int().positive().max(1000); const limitSchema = z.coerce.number().int().positive().max(1000);
const replayParamsSchema = z.object({ const replayParamsSchema = z.object({
after_ts: z.coerce.number().int().nonnegative().default(0), after_ts: z.coerce.number().int().nonnegative().default(0),
@ -157,9 +184,11 @@ const run = async () => {
database: env.CLICKHOUSE_DATABASE database: env.CLICKHOUSE_DATABASE
}); });
await retry("clickhouse table init", 20, 500, async () => {
await ensureOptionPrintsTable(clickhouse); await ensureOptionPrintsTable(clickhouse);
await ensureEquityPrintsTable(clickhouse); await ensureEquityPrintsTable(clickhouse);
await ensureFlowPacketsTable(clickhouse); await ensureFlowPacketsTable(clickhouse);
});
const optionSubscription = await subscribeJson( const optionSubscription = await subscribeJson(
js, js,

View file

@ -31,6 +31,33 @@ const envSchema = z.object({
const env = readEnv(envSchema); const env = readEnv(envSchema);
const retry = async <T>(
label: string,
attempts: number,
delayMs: number,
task: () => Promise<T>
): Promise<T> => {
let lastError: unknown;
for (let attempt = 1; attempt <= attempts; attempt += 1) {
try {
return await task();
} catch (error) {
lastError = error;
logger.warn(`${label} attempt failed`, {
attempt,
error: error instanceof Error ? error.message : String(error)
});
if (attempt < attempts) {
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
}
}
throw lastError ?? new Error(`${label} failed after retries`);
};
type ClusterState = { type ClusterState = {
contractId: string; contractId: string;
startTs: number; startTs: number;
@ -174,7 +201,9 @@ const run = async () => {
database: env.CLICKHOUSE_DATABASE database: env.CLICKHOUSE_DATABASE
}); });
await retry("clickhouse table init", 20, 500, async () => {
await ensureFlowPacketsTable(clickhouse); await ensureFlowPacketsTable(clickhouse);
});
const subscription = await subscribeJson( const subscription = await subscribeJson(
js, js,