Skip to content

[PA] Reset busy state on cancellation and chart switch#2857

Open
khairul-syazwan wants to merge 11 commits into
developfrom
khairul-syazwan/analyze-2852
Open

[PA] Reset busy state on cancellation and chart switch#2857
khairul-syazwan wants to merge 11 commits into
developfrom
khairul-syazwan/analyze-2852

Conversation

@khairul-syazwan

Copy link
Copy Markdown
Collaborator

Summary

Fixes #2852 — PA chart loading indicator could get stuck after navigating away and back, because chartBusy was never reset when an in-flight request was cancelled.

Root cause

fireQuery, fireBookmarkQuery, and several cohort-comparison charts used a module-level shared cancel token. When any new request started, it cancelled the previous one. The cancelled component then skipped busyEv(false) because the error message was 'cancel', leaving chartBusy = true permanently if the component was destroyed or replaced before another emit happened.

Changes

Store layer (removes shared cancellation)

  • src/store/modules/query.ts
  • src/store/modules/bookmark.ts
  • src/store/modules/cohortDefinition.ts
    These actions now accept an optional cancelToken from the caller instead of maintaining a shared cancel variable.

Active chart components

  • src/components/StackBarChart.vue — main chart used in PA; module-level stackBarChart moved to instance state, requests owned per instance
  • src/components/PatientListContainer.vue — patient list chart
  • src/components/ChartController.vue — resets chartBusy on chart switch and unmount
  • src/components/PatientAnalytics.vue — owns chartBusy; resets on active chart change and unmount

Other chart types (not the reported bug, but same leak)

  • src/components/KaplanMeier.vue
  • src/components/BoxplotChart.vue
  • src/components/SACChart.vue — previously never emitted busy state; now does

Cohort comparison charts (separate feature, same pattern)

  • src/components/StackBarCohortCompare.vue
  • src/components/BoxplotCohortCompare.vue
  • src/components/KMCohortCompare.vue
  • src/components/CohortComparisonContainer.vue — resets chartBusy on active chart switch and unmount

Tests

  • src/components/__tests__/StackBarChart.test.ts — added busy-state lifecycle tests
  • src/components/__tests__/PatientListContainer.test.ts — new test file for busy-state lifecycle
  • src/components/__tests__/__snapshots__/KaplanMeier.test.ts.snap — updated for added state fields

Files most important to the reported issue

The bug was reproduced with the stacked bar chart. The critical files are:

  • src/components/StackBarChart.vue
  • src/components/ChartController.vue
  • src/components/PatientAnalytics.vue
  • src/components/PatientListContainer.vue
  • src/store/modules/query.ts

Files not in the active reproduction path

These files fix the same busy-state leak but are not part of the create-cohort → navigate-away → return flow:

  • src/components/KaplanMeier.vue — only used when chart type is switched to KM
  • src/components/BoxplotChart.vue — only used when chart type is switched to boxplot
  • src/components/SACChart.vue — SAC custom charts feature
  • src/components/StackBarCohortCompare.vue — cohort comparison feature
  • src/components/BoxplotCohortCompare.vue — cohort comparison feature
  • src/components/KMCohortCompare.vue — cohort comparison feature
  • src/components/CohortComparisonContainer.vue — cohort comparison feature

How to test

  1. Create a new D2E cohort, open patient list, add a condition.
  2. Navigate away from Cohorts (e.g. to Dataset).
  3. Navigate back to Cohorts.
  4. Create another new D2E cohort.
    Expected: API fires and returns, chart renders; loading indicator does not stay stuck.

Verification

  • Targeted unit tests pass: StackBarChart, PatientListContainer, KaplanMeier, ChartController
  • Full suite: 588 passing, 3 pre-existing failures unrelated to this change (App.startup.test.ts, app-segmented-button.test.ts)

Merge Checklist

Please cross check this list if additions / modifications needs to be done on top of your core changes and tick them off. Reviewer can as well glance through and help the developer if something is missed out.

  • Automated Tests (Jasmine integration tests, Unit tests, and/or Performance tests)
  • Updated Manual tests / Demo Config
  • Documentation (Application guide, Admin guide, Markdown, Readme and/or Wiki)
  • Verified that local development environment is working with latest changes (integrated with latest develop branch)
  • following best practices in code review doc

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses PA charts’ loading indicator getting stuck by removing module-level shared cancellation tokens and ensuring chartBusy is reset on cancellation, unmount, and chart switches. It updates multiple chart components to own request cancellation per instance and adds/updates unit tests to cover the busy-state lifecycle.

Changes:

  • Refactors store actions to accept an optional caller-provided cancelToken instead of using shared module-level cancellation.
  • Updates PA and cohort-comparison chart components to manage per-instance request cancellation and consistently emit/reset busy state on unmount and chart switches.
  • Adds/updates unit tests and snapshots to validate busy-state lifecycle behavior.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
plugins/ui/apps/vue-mri-ui-lib/src/store/modules/query.ts Removes shared cancel token; fireQuery accepts optional cancelToken.
plugins/ui/apps/vue-mri-ui-lib/src/store/modules/bookmark.ts Removes shared cancel token; fireBookmarkQuery accepts optional cancelToken.
plugins/ui/apps/vue-mri-ui-lib/src/store/modules/cohortDefinition.ts Removes shared cancel token and updates actions toward caller-owned cancellation.
plugins/ui/apps/vue-mri-ui-lib/src/components/StackBarChart.vue Moves chart/request state to instance; adds per-instance cancellation + busy lifecycle handling.
plugins/ui/apps/vue-mri-ui-lib/src/components/PatientListContainer.vue Adds per-instance cancellation + busy lifecycle handling for patient list requests.
plugins/ui/apps/vue-mri-ui-lib/src/components/ChartController.vue Resets busy state on chart switch and unmount.
plugins/ui/apps/vue-mri-ui-lib/src/components/PatientAnalytics.vue Resets chartBusy on active chart change and unmount.
plugins/ui/apps/vue-mri-ui-lib/src/components/KaplanMeier.vue Adds per-instance cancellation + busy lifecycle handling for KM chart.
plugins/ui/apps/vue-mri-ui-lib/src/components/BoxplotChart.vue Adds per-instance cancellation + busy lifecycle handling for boxplot chart.
plugins/ui/apps/vue-mri-ui-lib/src/components/SACChart.vue Adds per-instance cancellation + ensures busy state is emitted/cleared.
plugins/ui/apps/vue-mri-ui-lib/src/components/StackBarCohortCompare.vue Moves chart/request state to instance; adds per-instance cancellation + busy lifecycle handling.
plugins/ui/apps/vue-mri-ui-lib/src/components/BoxplotCohortCompare.vue Refactors cohort-compare boxplot to per-instance cancellation + busy lifecycle handling.
plugins/ui/apps/vue-mri-ui-lib/src/components/KMCohortCompare.vue Refactors cohort-compare KM to per-instance cancellation + busy lifecycle handling.
plugins/ui/apps/vue-mri-ui-lib/src/components/CohortComparisonContainer.vue Resets busy state on active chart switches.
plugins/ui/apps/vue-mri-ui-lib/src/components/tests/StackBarChart.test.ts Adds tests for busy-state lifecycle, cancellation behavior, and unmount reset.
plugins/ui/apps/vue-mri-ui-lib/src/components/tests/PatientListContainer.test.ts Adds new tests for patient-list busy-state lifecycle and unmount reset.
plugins/ui/apps/vue-mri-ui-lib/src/components/tests/snapshots/KaplanMeier.test.ts.snap Updates snapshot for newly added request lifecycle state fields.
Comments suppressed due to low confidence (1)

plugins/ui/apps/vue-mri-ui-lib/src/store/modules/cohortDefinition.ts:203

  • fireGetAtlasCohortDefinitionQuery is declared with a third positional cancelToken parameter, but Vuex dispatch only passes a single payload argument. As written, callers can’t provide a cancelToken via dispatch (and this signature is inconsistent with the other actions updated to accept { cancelToken }).
  fireGetAtlasCohortDefinitionQuery({ commit, dispatch, getters, rootGetters }, cohortDefinitionId, cancelToken) {

    return dispatch('ajaxAuth', {
      url: `/d2e-webapi/cohortdefinition/${cohortDefinitionId}`,
      method: 'GET',
      cancelToken,
      datasetId: rootGetters.getSelectedDataset.id,

Comment thread plugins/ui/apps/vue-mri-ui-lib/src/components/StackBarChart.vue
Comment thread plugins/ui/apps/vue-mri-ui-lib/src/store/modules/bookmark.ts
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.

[Cohorts] PA stuck at loading indicator after exiting and re-entering

2 participants