fix(#5156): details page information fetching#5159
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the Spring Boot Admin UI instance details views to better react to SSE-driven instance updates by refetching/reinitializing metric-based panels and guarding against stale async responses.
Changes:
- Add “update-key” based refresh triggers (using
instance.version/statusTimestamp) across multiple instance detail panels. - Add stale-response protection for fetches (token/generation patterns) and restart polling subscriptions on instance updates.
- Extend the UI
Instancemodel with an optionalversionfield and add tests for the new behaviors.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/index.vue | Refetch metric index on instance update-key changes; add stale-response guarding. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/index.spec.ts | Adds SSE update + stale-response tests for metric index fetching. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-threads.vue | Reinitialize thread metrics/polling when instance update-key changes; adds takeUntil. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-threads.spec.ts | Adds SSE update test for threads view. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-metadata.vue | Fixes <script setup> props usage by avoiding non-reactive destructuring. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-memory.vue | Reinitialize memory metrics/polling when instance update-key changes; adds takeUntil. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-memory.spec.ts | Adds SSE update + stale poll-result tests for memory view. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-info.vue | Refetch info on instance id/version changes; adds stale-response guarding. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-info.spec.ts | Adds SSE update + stale-response tests for info view. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-health.vue | Adds token-based stale-response guarding and update-key tracking for health fetching. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-health.spec.ts | Adds SSE update + stale-response tests for health view. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-datasource.vue | Reinitialize datasource metrics/polling when instance update-key changes; adds takeUntil. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-datasource.spec.ts | Adds SSE update test for datasource view. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-cache.vue | Reinitialize cache metrics/polling when instance update-key changes; adds takeUntil. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-cache.spec.ts | Adds SSE update test for cache view. |
| spring-boot-admin-server-ui/src/main/frontend/services/instance.ts | Adds optional version field to the UI Instance type. |
| spring-boot-admin-server-ui/src/main/frontend/mixins/subscribing.ts | Introduces destroy$ subject and emits/completes it on unmount to help terminate streams. |
You can also share your feedback on Copilot code review. Take the survey.
spring-boot-admin-server-ui/src/main/frontend/views/instances/details/index.vue
Show resolved
Hide resolved
spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-info.vue
Show resolved
Hide resolved
spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-health.vue
Show resolved
Hide resolved
spring-boot-admin-server-ui/src/main/frontend/views/instances/details/index.spec.ts
Show resolved
Hide resolved
spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-info.spec.ts
Show resolved
Hide resolved
spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-memory.spec.ts
Show resolved
Hide resolved
spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-health.spec.ts
Show resolved
Hide resolved
62dcf54 to
98719f6
Compare
There was a problem hiding this comment.
Pull request overview
This PR strengthens the Spring Boot Admin UI instance-details views so they reliably refresh when an instance is updated (e.g., via SSE) by introducing an Instance.version update key, restarting polling/subscriptions on update, and adding stale-response protection and tests.
Changes:
- Add
version?: numberto theInstancemodel and use a derived “instance update key” (version/statusTimestamp/id) to trigger refetch/re-init. - Restart RxJS polling on instance updates and add
takeUntil-based teardown support via the subscribing mixin. - Add/extend UI tests to cover version-change refetching and stale-response scenarios.
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 |
|---|---|
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/index.vue | Refetch metric index on instance update key; add stale-response tokening. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/index.spec.ts | Adds tests for metric refetch-on-version-change and stale metric response handling. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-threads.vue | Restart threads polling on instance update key; add takeUntil(destroy$). |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-threads.spec.ts | Adds test ensuring threads reinitialize on instance version change. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-metadata.vue | Minor props handling refactor (props.instance usage). |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-memory.vue | Restart memory polling on instance update key; add takeUntil(destroy$). |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-memory.spec.ts | Adds tests for resubscribe-on-version-change and stale poll result suppression. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-info.vue | Add request-generation tokening and refetch on version/statusTimestamp changes. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-info.spec.ts | Adds tests for info refetch-on-version-change and stale info response suppression. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-health.vue | Add fetch tokening and health-group fetch staleness handling; adjust watcher behavior. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-health.spec.ts | Adds tests for health refetch-on-version-change, stale response suppression, and startup fetch count. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-datasource.vue | Restart datasource polling on instance update key; add takeUntil(destroy$). |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-datasource.spec.ts | Adds test ensuring datasource metrics reinitialize on version change. |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-cache.vue | Restart cache polling on instance update key; add takeUntil(destroy$). |
| spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-cache.spec.ts | Adds test ensuring cache metrics reinitialize on version change. |
| spring-boot-admin-server-ui/src/main/frontend/services/instance.ts | Adds version?: number to Instance and its data shape. |
| spring-boot-admin-server-ui/src/main/frontend/mixins/subscribing.ts | Introduces destroy$ Subject and emits/completes it on unmount for RxJS cleanup. |
| // Reset immediately so SSE updates can't leave stale gating behind. | ||
| this.metrics = []; | ||
| this.error = null; | ||
|
|
||
| if (!this.instance.hasEndpoint('metrics')) { | ||
| this.hasLoaded = true; | ||
| return; | ||
| } |
There was a problem hiding this comment.
fetchMetricIndex() only increments metricFetchToken after the hasEndpoint('metrics') check. If the previous instance had the metrics endpoint (and an in-flight fetchMetrics() is pending) but the updated instance does not, the token never changes and the stale response can still apply, repopulating metrics for an instance that no longer has the endpoint. Increment/invalidate the token before the endpoint check (or also bump it on the early-return path) so any prior requests are ignored.
| throw e; | ||
| } | ||
| return null; |
There was a problem hiding this comment.
The health-group fetch error handling looks inverted: the comment says to suppress errors only when the request became stale, but the code currently returns null for non-stale errors and throws when stale. This hides real fetchHealthGroup failures (groups silently disappear) while not actually helping with staleness. Adjust the condition so non-stale errors propagate/are handled, and stale errors are ignored.
| throw e; | |
| } | |
| return null; | |
| return null; | |
| } | |
| throw e; |
| watch: { | ||
| instance: { | ||
| handler: 'reloadHealth', | ||
| handler: 'fetchHealth', | ||
| immediate: true, | ||
| }, | ||
| }, | ||
| created() { | ||
| this.fetchHealth(); | ||
| }, | ||
| methods: { | ||
| reloadHealth() { | ||
| if (this.instance.id !== this.currentInstanceId) { | ||
| const updateKey = | ||
| this.instance.version ?? | ||
| this.instance.statusTimestamp ?? | ||
| this.instance.id; | ||
| if ( | ||
| this.instance.id !== this.currentInstanceId || | ||
| updateKey !== this.currentInstanceUpdateKey | ||
| ) { | ||
| this.fetchHealth(); | ||
| } | ||
| }, |
There was a problem hiding this comment.
reloadHealth() now contains the instance update-key logic, but the watcher was changed to call fetchHealth directly. As a result reloadHealth() is unused dead code and the update-key guard is bypassed (health will refetch on every instance reference change). Either remove reloadHealth() or switch the watcher back to use it so the intended guard is applied.
| const loading = ref(false); | ||
| const liveInfo = ref(null); | ||
| const currentInstanceId = ref(null); | ||
| const currentInstanceUpdateKey = ref(null); | ||
| const requestGen = ref(0); | ||
|
|
||
| const info = computed(() => formatInfo(liveInfo.value || props.instance.info)); | ||
| const isEmptyInfo = computed(() => Object.keys(info.value).length <= 0); | ||
|
|
||
| async function fetchInfo() { | ||
| if (props.instance.hasEndpoint('info')) { | ||
| const gen = ++requestGen.value; | ||
|
|
||
| currentInstanceId.value = props.instance.id; | ||
| currentInstanceUpdateKey.value = | ||
| props.instance.version ?? | ||
| props.instance.statusTimestamp ?? | ||
| props.instance.id; |
There was a problem hiding this comment.
currentInstanceId and currentInstanceUpdateKey are assigned in fetchInfo(), but they are no longer read anywhere (the old conditional in reloadInfo() was removed). Consider removing these refs (and their assignments) to keep the component state minimal and avoid implying they affect behavior.
This pull request improves how the UI components for instance details (health, cache, and datasource) handle updates when an instance's version changes, especially in response to server-sent events (SSE). The main goal is to ensure that metrics and health data are reliably refreshed when the instance changes, and that stale responses do not overwrite newer data. The changes also add comprehensive tests to verify this behavior.
Instance Update Handling and Data Refresh:
versionproperty is added to theInstancemodel and related types, enabling more precise detection of instance updates. [1] [2]details-cache.vue,details-datasource.vue,details-health.vue) now track anupdateKey(based onversion,statusTimestamp, orid) to determine when to reinitialize or refetch data if the instance changes. [1] [2] [3] [4] [5] [6]takeUntilis used to clean up polling subscriptions when components unmount or when the instance updates, preventing memory leaks and stale data. [1] [2] [3]Stale Response Protection:
details-health.vue) uses afetchTokento ignore stale responses from previous requests if the instance updates quickly, ensuring only the latest data is displayed. [1] [2]Testing Enhancements:
Supporting Refactors:
Applicationclass for consistency and to support the newversionproperty.These changes collectively make the UI more robust and responsive to backend instance updates, especially in dynamic environments with frequent instance changes.
References: