fix: fail the task chain when time-series retrieval fails (#2063) - #2065
Merged
Conversation
TimeSeriesDataRetrievalTask caught every exception, recorded it under StringKey_timeSeriesJobException and returned normally. Four of its six callers never read that key, so the next task ran against a null result: the user saw an NPE in an unrelated plotting task and the real cause was discarded. A cancellation went the same way, because UserCancelException was swallowed with everything else. Failing the chain is now the default, which is what five of the six callers want. ClientTaskDispatcher already does the right thing with a thrown exception - UserCancelException goes to TASK_ABORTED_BY_USER quietly, anything else raises an error dialog naming the real cause - so those callers need no change of their own. This also fixes the surface-movie path, which used to open a save-file chooser and only then discover it had no data. KymographPanel is the exception: it reports failures inside the panel through failMethod() and folds in TASK_ABORTED_BY_USER, so it opts back in through the new recordingFailure() factory. The matching check in PDEDataViewer's time-plot task is now unreachable and has been removed rather than left to suggest the key can still be set. Fixes #2063 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D71LBYmQNf5J94wPqr81Jx
Five tests over TimeSeriesDataRetrievalTask: a failure and a cancellation both abort the chain carrying the original cause, recordingFailure() still records instead of throwing for KymographPanel, a success publishes its results, and the data-job listener is removed however the task ends. Checked against the old behaviour: three of the five fail without the fix, and the two that pass are the two that should. Refs #2063 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D71LBYmQNf5J94wPqr81Jx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2063. Takes the inverted-default approach rather than the contained one.
What was wrong
PDEDataViewer.TimeSeriesDataRetrievalTaskcaught every exception, recorded it underStringKey_timeSeriesJobExceptionand returned normally:Four of its six callers never read that key. The dispatcher therefore treated the task as
successful and ran the next one against a null result. What the user saw was an NPE in an
unrelated plotting task, with the real cause thrown away. A cancellation went the same way,
since
UserCancelExceptionwas swallowed along with everything else.PdeTimePlotMultipleVariablesPanel:201PDEDataViewer:1177plotSpaceStatsdereferencesgetVariableNames()immediatelyPDEDataViewer:3013plotSpaceStatsPDEDataViewer:3072PDEDataViewer:2624KymographPanel:2035The fix
Throwing is now the default.
ClientTaskDispatcheralready does exactly the right thing with athrown exception —
recordExceptionroutesUserCancelExceptiontoTASK_ABORTED_BY_USERandstays quiet, while anything else becomes
TASK_ABORTED_BY_ERRORand an error dialog naming thereal cause — so the four broken callers are fixed without touching them, including the
save-file-chooser ordering at 3072.
KymographPanelis the reason a blanket rethrow would have been wrong. It reports failuresinside the panel via
failMethod()and also folds inTASK_ABORTED_BY_USER; rethrowing wouldhave skipped task3 and lost that handling entirely. It opts back in through a new
TimeSeriesDataRetrievalTask.recordingFailure(...)factory.The matching check in
PDEDataViewer:2624's task is now unreachable, so it is removed ratherthan left implying the key can still be set.
One thing that made this safe to reason about: the
TimeSeriesDataJobListenerDATA_COMPLETE/DATA_FAILUREhashtable writes are commented out, so the synchronous task is the only writerof either key — there is no async race here.
Tests
New
TimeSeriesDataRetrievalTaskTest(5 tests,Fast): a failure and a cancellation both abortthe chain carrying the original cause,
recordingFailure()still records instead of throwing,a success publishes its results, and the data-job listener is removed however the task ends.
I checked them against the old behaviour rather than assuming they bite — reverting just the
throwmakes 3 of the 5 fail, and the 2 that pass are the 2 that should (recordingFailureand the success path).
Verification
TimeSeriesDataRetrievalTaskTest— 5/5, and 3/5 fail without the fixvcell-clientFast — 36 tests, 0 failures, 0 errorsmvn compile test-compileacross all modules — cleanNot covered by automated tests: the kymograph's in-panel failure message and the dispatcher's
error dialog are Swing paths. The kymograph call site is a one-line change to the factory with
its downstream logic untouched, so the risk is confined to that panel still receiving the
recorded exception — which the test asserts directly.
🤖 Generated with Claude Code
https://claude.ai/code/session_01D71LBYmQNf5J94wPqr81Jx