Skip to content

Commit 7ad2970

Browse files
committed
feat(init): pre-read common config files to reduce round-trips
After computing the directory listing, pre-read ~35 common config files (manifests, framework configs, Sentry configs) if they exist. Send the results as fileCache in the startAsync input data. Workflow steps already check fileCache before suspending for read-files, so this eliminates 1-3 HTTP round-trips with no server-side changes needed (the fileCache field is already in step schemas). Capped at 512KB total to avoid sending excessive data upfront. Made-with: Cursor
1 parent 74898e8 commit 7ad2970

2 files changed

Lines changed: 87 additions & 1 deletion

File tree

src/lib/init/local-ops.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,83 @@ export async function precomputeDirListing(
284284
return (result.data as { entries?: DirEntry[] })?.entries ?? [];
285285
}
286286

287+
/**
288+
* Common config file names that are frequently requested by multiple workflow
289+
* steps (discover-context, detect-platform, plan-codemods). Pre-reading them
290+
* eliminates 1-3 suspend/resume round-trips.
291+
*/
292+
const COMMON_CONFIG_FILES = [
293+
"package.json",
294+
"tsconfig.json",
295+
"pyproject.toml",
296+
"Gemfile",
297+
"go.mod",
298+
"build.gradle",
299+
"build.gradle.kts",
300+
"pom.xml",
301+
"Cargo.toml",
302+
"pubspec.yaml",
303+
"mix.exs",
304+
"composer.json",
305+
"next.config.js",
306+
"next.config.mjs",
307+
"next.config.ts",
308+
"nuxt.config.ts",
309+
"nuxt.config.js",
310+
"angular.json",
311+
"astro.config.mjs",
312+
"astro.config.ts",
313+
"svelte.config.js",
314+
"remix.config.js",
315+
"vite.config.ts",
316+
"vite.config.js",
317+
"webpack.config.js",
318+
"sentry.client.config.ts",
319+
"sentry.client.config.js",
320+
"sentry.server.config.ts",
321+
"sentry.server.config.js",
322+
"sentry.edge.config.ts",
323+
"sentry.edge.config.js",
324+
"instrumentation.ts",
325+
"instrumentation.js",
326+
];
327+
328+
const MAX_PREREAD_TOTAL_BYTES = 512 * 1024;
329+
330+
/**
331+
* Pre-read common config files that exist in the directory listing.
332+
* Returns a fileCache map (path -> content or null) that the server
333+
* can use to skip read-files suspend/resume round-trips.
334+
*/
335+
export async function preReadCommonFiles(
336+
directory: string,
337+
dirListing: DirEntry[]
338+
): Promise<Record<string, string | null>> {
339+
const listingPaths = new Set(dirListing.map((e) => e.path));
340+
const toRead = COMMON_CONFIG_FILES.filter((f) => listingPaths.has(f));
341+
342+
const cache: Record<string, string | null> = {};
343+
let totalBytes = 0;
344+
345+
for (const filePath of toRead) {
346+
if (totalBytes >= MAX_PREREAD_TOTAL_BYTES) {
347+
break;
348+
}
349+
try {
350+
const absPath = path.join(directory, filePath);
351+
const content = await fs.promises.readFile(absPath, "utf-8");
352+
if (totalBytes + content.length <= MAX_PREREAD_TOTAL_BYTES) {
353+
cache[filePath] = content;
354+
totalBytes += content.length;
355+
}
356+
} catch {
357+
cache[filePath] = null;
358+
}
359+
}
360+
361+
return cache;
362+
}
363+
287364
export async function handleLocalOp(
288365
payload: LocalOpPayload,
289366
options: WizardOptions

src/lib/init/wizard-runner.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
detectExistingProject,
4848
handleLocalOp,
4949
precomputeDirListing,
50+
preReadCommonFiles,
5051
resolveOrgSlug,
5152
tryGetExistingProject,
5253
} from "./local-ops.js";
@@ -616,12 +617,20 @@ export async function runWizard(initialOptions: WizardOptions): Promise<void> {
616617
let result: WorkflowRunResult;
617618
try {
618619
const dirListing = await precomputeDirListing(directory);
620+
const fileCache = await preReadCommonFiles(directory, dirListing);
619621
spin.message("Connecting to wizard...");
620622
run = await workflow.createRun();
621623
result = assertWorkflowResult(
622624
await withTimeout(
623625
run.startAsync({
624-
inputData: { directory, yes, dryRun, features, dirListing },
626+
inputData: {
627+
directory,
628+
yes,
629+
dryRun,
630+
features,
631+
dirListing,
632+
fileCache,
633+
},
625634
tracingOptions,
626635
}),
627636
API_TIMEOUT_MS,

0 commit comments

Comments
 (0)