jenwitteng opened a new pull request, #42157:
URL: https://github.com/apache/superset/pull/42157

   ### SUMMARY
   
   With `GLOBAL_ASYNC_QUERIES` enabled, uncached chart-data requests return 
**HTTP 202** with job metadata (`channel_id`, `job_id`, `result_url`) rather 
than inline results. Every Matrixify grid cell renders through `StatefulChart` 
(`@superset-ui/core`), which previously treated that 202 body as chart data — 
so each cell showed **"No data"** until a manual refresh warmed the cache.
   
   `StatefulChart` now detects a 202 and delegates to an injected 
`handleAsyncChartData` hook, which polls the async event channel and resolves 
the cached results. The handler is wired in from `ChartRenderer` (reusing the 
existing `handleChartDataResponse` / `waitForAsyncData`) and flows through the 
standard hooks chain, keeping `superset-ui-core` decoupled from app-level 
async-event middleware. If a 202 arrives with no handler, `StatefulChart` fails 
loudly instead of silently rendering empty data.
   
   Because a matrix fires many concurrent per-cell requests that can be 
superseded by filter/formData changes and unmounted by scrolling, the change 
also hardens the async lifecycle:
   
   - **Correct response shapes** — the legacy endpoint's flat 202 body is 
wrapped as `{ result: [body] }` to match the V1 signature the async handler 
expects (legacy async previously received `undefined`); V1 bodies pass through 
unchanged.
   - **Supersession guards** — each request captures its own `AbortController`; 
a late sync/async result or error is discarded if a newer request has 
superseded it, so stale data can't overwrite fresh chart data.
   - **Cancellation & no leaks** — `waitForAsyncData` accepts an `AbortSignal`, 
removes its event listener on abort/unmount (no leaked listeners keeping the 
poller busy), and cancels the in-flight cached-result download when aborted 
mid-fetch.
   - **Latest props on refetch** — `fetchData` reads current props via a ref 
(it's memoized with an empty dep list), so updated filters/formData are used on 
refetch.
   - **Render-only changes preserved** — resolving an older async request 
renders with the latest formData, so color/zoom changes aren't reverted.
   - **Detailed error messages** — array-shaped `waitForAsyncData` rejections 
are unwrapped so the parsed client-error message survives instead of collapsing 
to a generic "An error occurred".
   
   This supersedes #42033, which was built from a `master` snapshot that 
predated the `Map`-based `listenersByJobId`/`retriesByJobId` refactor in 
#40747; rebasing surfaced that mismatch (flagged by review as a `Record` 
prototype-pollution regression) along with two other guards 
(stale-response/stale-failure dedup and the per-result warning toast in 
`exploreJSON`) that were dropped in the original diff. All three are restored 
here, and the branch is rebased onto current `master`.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   **BEFORE:** Matrixify cells show "No data" on first load when cache is cold.
   <img width="1676" height="595" alt="Screenshot before" 
src="https://github.com/user-attachments/assets/c8cc7c32-cfff-47fa-934f-6bf4890d47c6";
 />
   
   **AFTER:** Cells show loading state, then resolve and render charts without 
requiring a manual refresh.
   <img width="1684" height="727" alt="Screenshot after" 
src="https://github.com/user-attachments/assets/3c399c72-8c32-46e1-b18c-1b3cab77c2c8";
 />
   
   ### TESTING INSTRUCTIONS
   
   1. Enable `GLOBAL_ASYNC_QUERIES` (and its required Celery worker + 
cache/results backend + websocket/polling config)
   2. Open a dashboard containing a Matrixify chart whose per-cell queries are 
**not** already cached (clear cache or use `force`)
   3. Verify cells show a loading state, then resolve and render each chart on 
first load (not "No data")
   4. Verify a **legacy-API** viz (e.g. deck.gl / world map / country map) in a 
matrix cell also resolves
   5. Rapidly change a dashboard filter while cells are still resolving — 
confirm cells settle on the **latest** filter's data (no stale overwrite) and 
no console errors/leaked listeners
   6. Scroll a large matrix so cells unmount mid-load — confirm no "setState on 
unmounted component" warnings and pending downloads are cancelled
   7. Run automated tests:
      ```bash
      cd superset-frontend
      npm run test -- StatefulChart.test.tsx
      npm run test -- asyncEvent.test.ts
      npm run test -- chartActions.test.ts
      npm run test -- ChartRenderer.test.tsx
      ```
   
   ### ADDITIONAL INFORMATION
   
   - [ ] Has associated issue:
   - [x] Required feature flags: `GLOBAL_ASYNC_QUERIES` (behavior only differs 
when enabled; unchanged when off)
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to