Skip to content

fix(ui-react): save the Models step by diff, not delete-then-insert (#107) - #121

Merged
mosoriob merged 1 commit into
developfrom
fix/107-models-step-continue
Aug 11, 2026
Merged

fix(ui-react): save the Models step by diff, not delete-then-insert (#107)#121
mosoriob merged 1 commit into
developfrom
fix/107-models-step-continue

Conversation

@mosoriob

Copy link
Copy Markdown
Contributor

Fixes #107.

The fault

SetThreadModels deleted every thread_model row for the thread, then re-inserted the
selection. All four tables that reference thread_model.id are ON DELETE RESTRICT
(thread_model_execution_summary, thread_model_execution, thread_model_io,
thread_model_parameter), so the delete was refused as soon as the thread held any of them.
After a thread passed Datasets once, its model selection could never be changed again.

ModelsStep.tsx used try { … } finally {} with no catch, so the rejection was unhandled:
no toast, no navigation, nothing.

The fix

diffThreadModels (src/lib/thread-models.ts) compares the selection against what is stored:

  • a configuration that stays selected keeps its row and its id, so the dataset and
    parameter bindings hanging off it survive a trip back through the step;
  • only deselected rows are deleted, and the mutation deletes their four child rows first,
    scoped to those ids;
  • only new configurations are inserted;
  • an unchanged selection writes nothing at all — pressing Continue a second time is now a
    no-op instead of a failure.

Lit avoids the RESTRICT wall by deleting every child row for the thread on every save
(ui/src/queries/thread/update-models.graphql). This does not copy that: a save that changes
nothing must not destroy the later steps' work.

A thread_model row with no modelcatalog_configuration_id is left alone. The step cannot
display or select it, threadModelFromGQL already skips it, and deleting it would hit the same
RESTRICT wall on any legacy thread that holds runs. TACC's database holds 21 of them across 109
thread_model rows, measured anonymously.

Both call sites are fixed — ModelsStep (the wizard) and MintModels (the expansion panel) —
and both now surface a failed save as a Save failed toast.

Not fixed here

Removing a model still discards that model's bindings and runs, without warning. Lit does the
same for every model on every save, so this is not a regression; a confirmation step is a
separate question.

Tests

npm test — 921 passing. The four new ModelsStep assertions were checked to fail against the
old code; they assert the outgoing mutation variables, not component state.

Still to do: verify live at TACC under a real Tapis token.

…107)

SetThreadModels deleted every thread_model row for the thread and re-inserted
the selection. All four tables that reference thread_model.id are ON DELETE
RESTRICT, so once a thread had been through the Datasets or Parameters step the
delete was refused and Continue became a dead end. ModelsStep had no catch, so
the rejection was swallowed: no toast, no navigation, nothing.

diffThreadModels keeps the rows whose configuration is still selected, deletes
only the rows whose configuration is not, and inserts only what is new. A kept
row keeps its id, so the dataset and parameter bindings hanging off it survive a
trip back through the step. An unchanged selection writes nothing at all.

Removing a model still discards that model's bindings and runs — the mutation
deletes its four child rows first, scoped to the removed ids. A thread_model row
with no modelcatalog_configuration_id is left alone: the step cannot show it,
threadModelFromGQL skips it, and deleting it would hit the same RESTRICT wall.
TACC holds 21 such rows out of 109.

Both call sites are fixed, and both now report a failed save.
@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
monorepo Ready Ready Preview Aug 11, 2026 12:58am

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant