submit: reject runs whose output would overwrite an existing fig

Before dispatching to Prefect, check if figs/<stem>.html already exists.
If so, return 409 with a message asking to bump seed/jitter/N/T or delete
the fig. Stem is derived from (generator, embedder, N, T, J, seed), so
embed_args-only changes still collide and are blocked — users must vary
a stem-shaping param to get a distinct output file.
This commit is contained in:
Michael Pilosov 2026-04-22 15:39:05 -06:00
parent a5614ac371
commit 36e217f51e

View File

@ -751,6 +751,24 @@ async def submit(request: Request) -> HTMLResponse:
embed_args = build_embed_args(reducer, data) embed_args = build_embed_args(reducer, data)
# Reject submissions whose output path would overwrite an existing fig.
# The stem is fully determined by (generator, embedder, N, T, J, seed) —
# embed_args don't affect the filename, so e.g. UMAP(n_neighbors=5) and
# UMAP(n_neighbors=15) with otherwise-matching params collide too. Force
# the user to change a stem-shaping param (seed is usually cheapest) or
# delete the existing fig first.
_, emb_file = synthesize_output_paths(
generator_path, reducer, num_points, num_timesteps, jitter_scale, seed
)
if (FIGS_DIR / emb_file).exists():
return HTMLResponse(
f"<div class='flash err'>a run with these params already exists "
f"(<code>{emb_file}</code>). change <code>seed</code> / "
f"<code>jitter</code> / <code>N</code> / <code>T</code>, or delete "
f"the fig first.</div>",
status_code=409,
)
parameters: Dict[str, Any] = { parameters: Dict[str, Any] = {
"num_points": num_points, "num_points": num_points,
"num_timesteps": num_timesteps, "num_timesteps": num_timesteps,