Skip to content

fix: skip restored state for datasets that failed to load, plus test cleanups - #960

Merged
PaulHax merged 9 commits into
Kitware:mainfrom
PaulHax:stack/01-independent-fixes
Sep 21, 2026
Merged

PaulHax merged 9 commits into
Kitware:mainfrom
PaulHax:stack/01-independent-fixes

Conversation

@PaulHax

@PaulHax PaulHax commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Small fixes and test cleanups that stand on their own. They were written alongside the segmentation work in #950 but do not depend on it, so they are split out here to keep that review smaller.

Restoring a session whose dataset failed to load

A dataset that cannot be reached is absent from the restore id map. Several restore paths mapped saved ids through it without checking:

  • Saved crops were seated under the key undefined and written back out on every later save.
  • A saved layer with a missing parent left parentToLayers[undefined] = undefined, and the next save threw before writing anything. A missing source left a layer the manifest schema rejects, which dropped the parent's valid layers from the file.
  • View configs of datasets that did not restore are skipped the same way.
  • A failed layer build no longer leaves an undefined layer list behind.

Processing

The job history load now expires the session on a 401, as polling, cancel and result loading already do. Before, the session stayed live and the panel offered a Retry that could only 401 again.

State file

Drops the paint labelmapOpacity schema field, which nothing reads or writes.

Tests

  • The DICOM chunk image spec, the two DICOM store specs and the two DICOM end-to-end specs share their repeated setup through helpers. onRegularChunkHasData delegates its three rejections to named assertions. No assertion, behaviour or error message changed. This clears the duplication and complexity that a follow-up change adding quality ratchets to CI would otherwise flag.
  • A missing screenshot baseline fails in CI instead of being written and passing. Local runs still write new baselines.
  • The stream fetcher's stop and resume test drives its own stream instead of depending on network timing.

…exity

The duplication ratchet found four clones inside the DICOM chunk image spec,
one shared by the two DICOM store specs, and one shared by the two new DICOM
end-to-end specs. The complexity ratchet found onRegularChunkHasData at 18.

The chunk image spec builds its held-open decodes with one deferredDecoder
helper, shares the re-sorted chunk setup the three staleness tests need, and
asserts slice contents through expectSliceValues. The two store specs build
their instance tags from a shared fixture. The end-to-end specs make their
scratch directory with a makeTempDir helper in the existing test utils. No
assertion changed.

onRegularChunkHasData delegates its three rejections to
assertSingleFramePerFile, assertChunkFitsSlot and assertSamplesRepresentable,
which also removes the repeated "File X (chunk N)" prefix. Behaviour and error
messages are unchanged.
Restoring a state file mapped each saved crop entry's image id through the
restore dataIDMap without checking that the image had actually loaded. A
dataset that could not be reached is absent from that map, so its saved planes
were seated under the key `undefined`, clamped against an empty extent to a
degenerate zero-width crop.

No image with that id is ever deleted, so the store's onImageDeleted cascade
could never drop the entry: it survived in `tools.crop` and was written back
out on every later save, leaving the saved manifest with a crop keyed by an
image no dataset in the file describes, which the dev-only save backstop
reports as a dangling reference.

Deserialization now skips a saved crop whose image did not resolve, so the
crops of resolved images survive a save unchanged.
Restoring a state file mapped each saved layer relationship's parent and source
through the restore dataIDMap without checking that either image had actually
loaded. A dataset that could not be reached is absent from that map, so
addLayer was handed a missing id and only failed once the build was under way.

A missing parent was the worse of the two. addLayer's failure path assigns
`parentToLayers[parent]` the result of filtering a list that is not there, which
seats the key `undefined` with the value `undefined`. Serialize maps over every
entry, so the next save threw a TypeError before it could write anything, and
the user saw only a failed save. A missing source instead left a layer whose
selection was undefined hanging off a real parent, and the save wrote that
parent's whole relationship with an undefined source key, which the manifest
schema rejects: the parent's valid layers were dropped from the file with it.

Deserialization now skips a saved relationship whose parent did not resolve and
each source that did not resolve, so the layers of resolved images are built
and saved unchanged.
Polling, cancel and result loading all classify their errors and hand a 401 to
markSessionExpired. The job-history load did not: it logged and recorded a
per-provider string, so the session stayed live in the store, the persistent
reload notice never appeared, and the panel offered a Retry that could only
401 again.

Its catch now goes through expireSessionIf first, and both the history request
and the page loop stop once the session is expired, so nothing re-issues a
request that cannot succeed. The two catches build their detail string in a
local, which keeps the file inside the line ratchet. A case in the store spec
drives a 401 listing through adoption and asserts the notice, the empty history
error, and that a retry sends nothing.
@netlify

netlify Bot commented Sep 21, 2026

Copy link
Copy Markdown

Deploy Preview for volview-dev ready!

Name Link
🔨 Latest commit c3df55b
🔍 Latest deploy log https://app.netlify.com/projects/volview-dev/deploys/6ab179c51ce6210008a5eed2
😎 Deploy Preview https://deploy-preview-960--volview-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@PaulHax
PaulHax merged commit 3697368 into Kitware:main Sep 21, 2026
8 checks passed
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