This is an automated email from the ASF dual-hosted git repository.

wu-sheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git


The following commit(s) were added to refs/heads/main by this push:
     new 1421f2d  ui: revert instance prefetch, wire service list to 
auto-refresh ticker
1421f2d is described below

commit 1421f2d551ae2e2cd1b56abe22c63a0d0a37b24e
Author: Wu Sheng <[email protected]>
AuthorDate: Sun May 17 19:26:16 2026 +0800

    ui: revert instance prefetch, wire service list to auto-refresh ticker
    
    Per operator direction:
    
    1. Drop the usePrefetchLayerInstances prefetch added in 09f996b.
       It pre-warmed instance lists for every landing service in the
       background, which the operator explicitly didn't want — extra
       N BFF calls on every landing, and the click-time fetch was
       already fast enough once the cascade is wired correctly.
    
    2. Service list (useLayerLanding) is the layer's in-memory cache —
       stays cached aggressively (staleTime: Infinity, no window-focus
       refetch). Refresh paths are explicit:
         - Global auto-refresh ticker via useAutoRefreshSubscribe →
           refetch on each tick (operator-controlled cadence from the
           topbar).
         - Manual refresh button in LayerShell → q.refetch().
       No silent vue-query-driven refetch under the operator.
    
    Service-click flow stays as-is: setSelected drops ?instance= /
    ?endpoint= → dependent widgets reset to "Reading data…" → instance
    query refires → auto-pick → dashboard query → widgets land async.
    Each downstream control listens to its upstream and resets +
    shows loading words before its own query fires, matching the
    cascade-clear-then-load principle.
---
 apps/ui/src/layer/useLayerInstances.ts             | 51 ++--------------------
 apps/ui/src/layer/useLayerLanding.ts               | 18 +++++---
 .../render/layer-dashboard/LayerDashboardsView.vue | 13 +-----
 3 files changed, 15 insertions(+), 67 deletions(-)

diff --git a/apps/ui/src/layer/useLayerInstances.ts 
b/apps/ui/src/layer/useLayerInstances.ts
index 7238b19..2f7977a 100644
--- a/apps/ui/src/layer/useLayerInstances.ts
+++ b/apps/ui/src/layer/useLayerInstances.ts
@@ -22,18 +22,16 @@
  * BFF would reject as `missing_service`.
  */
 
-import { computed, watch, type Ref } from 'vue';
-import { useQuery, useQueryClient } from '@tanstack/vue-query';
+import { computed, type Ref } from 'vue';
+import { useQuery } from '@tanstack/vue-query';
 import { bffClient } from '@/api/client';
 
-const INSTANCES_STALE_MS = 60_000;
-
 export function useLayerInstances(layerKey: Ref<string>, service: Ref<string | 
null>) {
   const q = useQuery({
     queryKey: ['layer-instances', layerKey, service],
     queryFn: () => bffClient.layer.instances(layerKey.value, service.value ?? 
''),
     enabled: computed(() => layerKey.value.length > 0 && !!service.value),
-    staleTime: INSTANCES_STALE_MS,
+    staleTime: 30_000,
   });
   return {
     data: computed(() => q.data.value ?? null),
@@ -43,46 +41,3 @@ export function useLayerInstances(layerKey: Ref<string>, 
service: Ref<string | n
     error: q.error,
   };
 }
-
-/**
- * Background pre-fetch of instance lists for every service in the
- * supplied list. Run after the landing rows arrive so the operator's
- * very next service-switch click finds the new service's instance
- * list already in cache — eliminating the ~100-500ms BFF round-trip
- * that otherwise gates the dashboard refire.
- *
- * Uses vue-query's `prefetchQuery` so each fetch goes through the
- * SAME cache key as `useLayerInstances`. The active picker call
- * then hits the cache instantly with no duplicate request. Skips
- * services we already have cached + not stale.
- *
- * Idempotent (queryClient.prefetchQuery dedups in-flight requests
- * by key) and tied to the calling scope's watch so it re-runs when
- * the layer or service list changes (e.g. when the operator
- * navigates to a different layer or hits the refresh button).
- */
-export function usePrefetchLayerInstances(
-  layerKey: Ref<string>,
-  serviceIds: Ref<ReadonlyArray<string>>,
-): void {
-  const qc = useQueryClient();
-  watch(
-    [layerKey, serviceIds],
-    ([key, ids]) => {
-      if (!key) return;
-      for (const id of ids) {
-        if (!id) continue;
-        // Plain values in the key — vue-query serialises refs by
-        // their resolved .value, so this hashes to the same slot as
-        // the active `useLayerInstances` queryKey for the same
-        // (layerKey, id) pair.
-        void qc.prefetchQuery({
-          queryKey: ['layer-instances', key, id],
-          queryFn: () => bffClient.layer.instances(key, id),
-          staleTime: INSTANCES_STALE_MS,
-        });
-      }
-    },
-    { immediate: true },
-  );
-}
diff --git a/apps/ui/src/layer/useLayerLanding.ts 
b/apps/ui/src/layer/useLayerLanding.ts
index 52bfa1a..246b21e 100644
--- a/apps/ui/src/layer/useLayerLanding.ts
+++ b/apps/ui/src/layer/useLayerLanding.ts
@@ -17,6 +17,7 @@
 
 import { computed, type Ref } from 'vue';
 import { useQuery } from '@tanstack/vue-query';
+import { useAutoRefreshSubscribe } from '../controls/useAutoRefreshSubscribe';
 import type { LandingConfig, LandingResponse, LayerDef } from 
'@skywalking-horizon-ui/api-client';
 import { bffClient } from '@/api/client';
 
@@ -61,13 +62,14 @@ export function useLayerLanding(
     return `${r.step}:${Math.floor(r.startMs / 60_000)}:${Math.floor(r.endMs / 
60_000)}`;
   });
 
-  // Service list is fetched ONCE per (layer, cfg, range) and stays
-  // cached. No `refetchInterval`, no `refetchOnWindowFocus`, not
-  // wired into the global auto-refresh ticker: the operator-facing
-  // contract is "service list doesn't move under you". Manual
-  // refresh is the `q.refetch()` handle exposed below — wired to
-  // a refresh button in LayerShell so operators can pull a fresh
-  // list on demand.
+  // Service list is the layer's in-memory snapshot — cache it
+  // aggressively (staleTime: Infinity, no window-focus refetch).
+  // Two ways to refresh:
+  //   1. The global auto-refresh ticker (`useAutoRefreshSubscribe`
+  //      below) — operator pace, controlled from the topbar.
+  //   2. The manual refresh button in LayerShell — `q.refetch()`.
+  // No silent vue-query-driven refetch under the operator, so the
+  // service list never moves on its own between operator actions.
   const q = useQuery({
     queryKey: ['layer-landing', layerKey, cfgHash, rangeKey],
     queryFn: () =>
@@ -81,6 +83,8 @@ export function useLayerLanding(
     retry: 1,
   });
 
+  useAutoRefreshSubscribe(() => q.refetch());
+
   const data = computed<LandingResponse | null>(() => q.data.value ?? null);
   const rows = computed(() => data.value?.rows ?? []);
   const reachable = computed(() => data.value?.reachable ?? false);
diff --git a/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue 
b/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
index 23e97ab..246ba7f 100644
--- a/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
+++ b/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
@@ -35,7 +35,7 @@ import { colorForMetric } from '@/utils/metricColor';
 import { useLayerDashboard, useLayerDashboardConfig } from 
'@/render/layer-dashboard/useLayerDashboard';
 import { useLayerPageOrchestrator } from 
'@/render/layer-dashboard/useLayerPageOrchestrator';
 import { useLayerEndpoints } from '@/layer/useLayerEndpoints';
-import { useLayerInstances, usePrefetchLayerInstances } from 
'@/layer/useLayerInstances';
+import { useLayerInstances } from '@/layer/useLayerInstances';
 import { useLayerLanding } from '@/layer/useLayerLanding';
 import { useTimeRangeStore } from '@/controls/timeRange';
 import { useLayers } from '@/shell/useLayers';
@@ -148,17 +148,6 @@ const expandedInstance = ref<string | null>(null);
  *  bound to it. */
 const { setSelected: setSelectedService } = useSelectedService();
 const landingRows = computed(() => landing.data.value?.sampledRows ?? 
landing.rows.value ?? []);
-// Background pre-fetch — kick off instance-list requests for every
-// service in the landing as soon as rows arrive, so the operator's
-// next service-switch click finds the new service's instance list
-// already cached. Uses vue-query's prefetchQuery under the same
-// cache key as the active `useLayerInstances`, so no duplicate
-// requests fire. Eliminates the ~100-500ms BFF round-trip that
-// otherwise gates the dashboard refire on service change.
-usePrefetchLayerInstances(
-  layerKey,
-  computed(() => landingRows.value.map((r) => r.serviceId)),
-);
 watch(landingRows, (rows) => {
   const first = rows[0];
   if (!first) return;

Reply via email to