sancho11 commented on PR #41714:
URL: https://github.com/apache/superset/pull/41714#issuecomment-5189827707

   I've been running an adaptation of #41730 (the `deck_multi` migration merged 
into this branch) in production, on an instance with `GLOBAL_ASYNC_QUERIES` 
enabled and an embedded dashboard. It works, but I hit four issues that I think 
will show up for everyone once this lands. All four are in `Multi.tsx`, its 
metadata, none require changes to the removal itself.
   
   Sharing them here with the fixes I ended up with, in case they're useful. 
Happy to open a PR against this branch for any or all of them.
   
   Confidence, so you can weigh them: 2, 3 and 4 I watched fail in production 
and then traced to the code below. 1 I derived from the code and fixed before 
it could bite, so I have not actually witnessed it; treat it as a code reading 
rather than a report.
   
   ### 1. Autozoom silently stops working
   
   `getAdjustedViewport` still reads the container's pre-merged features:
   
   ```ts
   const features = props.payload?.data?.features || {};
   ```
   
   But the new `Multi/buildQuery.ts` returns `buildQueryContext(formData, () => 
[])`, so the container issues no query and that field is never populated. 
`points` ends up empty, `fitViewport` is never called, and the chart opens at 
the saved viewport instead of fitting the data. The `// there may be none here` 
comment in the diff acknowledges the empty case, but nothing replaces the 
points.
   
   Fix: collect the points from the features each layer's own `transformProps` 
returned, aggregated by `viz_type` after the layers resolve. This is arguably 
better than the old behavior, it fits the data actually being rendered rather 
than a separately-computed merge.
   
   ### 2. The container renders the "No results" empty state
   
   With `queries: []` the endpoint answers `result: []`, and in `SuperChart`:
   
   ```ts
   const noResultQueries =
     enableNoResults &&
     (!queriesData ||
       queriesData
         .slice(0, getQueryCount())
         .every(({ data }) => !data || (Array.isArray(data) && data.length === 
0)));
   ```
   
   `[].every(...)` is vacuously `true`, so the chart renders "No results were 
returned for this query" and the map never appears at all.
   
   `ChartMetadata` already carries `enableNoResults` for exactly this 
situation, but only the native-filter path reads it; `ChartRenderer` derives 
the flag solely from server pagination:
   
   ```ts
   const bypassNoResult = !(
     currentFormDataExtended?.server_pagination &&
     (hasSearchText || hasAgGridFilters)
   );
   ```
   
   Fix: honor `getChartMetadataRegistry().get(vizType)?.enableNoResults` there 
as well, and set `enableNoResults: false` on the Multiple Layers metadata. Also 
worth having `transformProps` not hand the container an `undefined` payload 
when `queriesData` is empty.
   
   ### 3. Layer lookup 404s for any principal whose chart access is scoped
   
   `fetchSubslices` reads each layer with `GET /api/v1/chart/<id>`. Layer 
charts are saved charts that normally sit on no dashboard of their own, so 
`ChartFilter` denies them:
   
   ```python
   if (guest_dashboards := guest_embedded_dashboard_filter()) is not None:
       return query.filter(self.model.dashboards.any(guest_dashboards))
   if security_manager.can_access_all_datasources():
       return query
   return self._apply_viewers(query)
   ```
   
   An embedded guest gets denied by the first branch (the layers are not on the 
token's dashboards) and a role without an explicit grant on the layer gets 
denied by `_apply_viewers`; in both cases even though the principal is entitled 
to the container. In our embedded dashboard every layer 404s, consistently.
   
   Confirming it was the filter and not a stale id or a missing session, for 
one of our layers:
   
   - `GET /api/v1/chart/369` as an admin returns `200`, so the chart exists and 
is readable.
   - Its payload has `"dashboards": []`; it is a layer of a `deck_multi` chart, 
so it sits on no dashboard of its own. `Slice.dashboards.any(<token 
dashboards>)` can therefore never match it.
   - The same request with no session returns `{"msg": "Missing Authorization 
Header"}`, not a `404`. So the `404` we saw came from a request that *was* 
authenticated and scoped, which is the guest branch above.
   
   Note this failure is deterministic rather than intermittent, so for embedded 
deployments it is the one that fully breaks the chart.
   
   The legacy pipeline never hit this because it resolved the layers 
server-side, under the container's access:
   
   ```python
   slices = db.session.query(Slice).filter(Slice.id.in_(slice_ids)).all()
   ```
   
   Fix: a `GET /chart/<pk>/deck_layers/` endpoint that gates on the container 
(the normal base filter applies to *that* lookup) and then resolves the 
declared layers with `skip_base_filter=True`, exposing only their `slice_id`, 
`viz_type` and `params`. That reproduces the legacy rule, access to the 
container governs access to its layers, without widening the general chart 
filter. `Multi.tsx` uses it when the container is saved and falls back to the 
per-chart reads otherwise, so an unsaved chart in Explore still works.
   
   Worth noting this also collapses N requests into one.
   
   ### 4. Sub-layer requests still take the async handoff
   
   This is the one that cost me the most time, so it may be the most valuable. 
`Multi.tsx` posts with `result_type: 'full'`, and in `charts/data/api.py`:
   
   ```python
   use_async = (
       is_feature_enabled("GLOBAL_ASYNC_QUERIES")
       and query_context.result_format == ChartDataResultFormat.JSON
       and query_context.result_type == ChartDataResultType.FULL
       and cache_timeout != CACHE_DISABLED_TIMEOUT
   )
   if use_async:
       return self._run_async(json_body, command, add_extra_log_payload)
   ```
   
   So with `GLOBAL_ASYNC_QUERIES` enabled and a cold cache, each sub-layer 
request answers `202` with job metadata and no data. `Multi.tsx` posts directly 
with `SupersetClient.post` rather than through the chart pipeline, so it never 
registers a listener and cannot follow the job. The layer simply never renders, 
and the async middleware logs one of these per layer:
   
   ```
   listener not found for job_id 9301681d-69e7-40c6-837a-83f1dcc9e7ce
   ```
   
   It presents as intermittent and "fixed by reloading", because by the time 
you reload the job has completed and warmed the cache. That made it quite hard 
to chase.
   
   Note this is the *same* failure the legacy path had on `/explore_json/` -> 
moving to `/api/v1/chart/data` carries it along rather than resolving it.
   
   Fix: request `result_type: 'results'` instead of `'full'`. Both share the 
same preparer (`None` in `_data_result_type_preparers`), so it is the same 
query against the same cache; only the payload envelope is trimmed, and it 
still returns `data` / `colnames` / `coltypes`, which is all the layer 
transforms read (`getRecordsFromQuery` uses `queriesData[0].data`).
   
   ---
   
   If it helps in prioritizing: #2 and #3 break the chart completely and 
deterministically; #2 for everyone, #3 for embedded deployments; while #4 
presents as intermittent and self-healing, which made it by far the most 
expensive to diagnose.
   


-- 
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