Skip to content

Conversation

@ktx-abhay
Copy link
Collaborator

@ktx-abhay ktx-abhay commented Sep 12, 2025

PR Type

Bug fix


Description

  • Skip state updates for empty streaming hits

  • Prevent overwriting data with empty arrays

  • Apply fix across loader code paths


Diagram Walkthrough

flowchart LR
  Source["searchRes (streaming_aggs)"] -- "hits length > 0 ?" --> Check["Check hits length"]
  Check -- "Yes" --> Update["Update state.data[currentQueryIndex]"]
  Check -- "No" --> Skip["Skip state update"]
Loading

File Walkthrough

Relevant files
Bug fix
usePanelDataLoader.ts
Guard state updates against empty streaming hits                 

web/src/composables/dashboard/usePanelDataLoader.ts

  • Guard assignments with hits length checks.
  • Avoid replacing state when hits are empty.
  • Apply checks in three streaming_aggs branches.
+16/-7   

@github-actions github-actions bot added the ☢️ Bug Something isn't working label Sep 12, 2025
@ktx-abhay ktx-abhay requested a review from omkarK06 September 12, 2025 07:28
@github-actions
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Type Bug

Using object spread fallback for hits (...(hits ?? {})) results in array from object keys when hits is undefined/null; this likely should default to an empty array to avoid corrupting state.

state.data[payload?.meta?.currentQueryIndex] = [
  ...(searchRes?.content?.results?.hits ?? {}),
];
Consistency

First code path uses searchRes.data.hits while others use searchRes.content.results.hits; ensure shapes are intentionally different and consistently guarded to avoid runtime errors.

  // handle empty hits case
  if (searchRes?.data?.hits?.length > 0) {
    state.data[currentQueryIndex] = [...searchRes.data.hits];
  }
}
Edge Case

Guard only checks hits.length > 0; if hits is an empty array and prior state exists, skipping update preserves old data—confirm this is the desired behavior for all streaming scenarios.

// handle empty hits case
if (searchRes?.content?.results?.hits?.length > 0) {
  state.data[payload?.meta?.currentQueryIndex] = [
    ...(searchRes?.content?.results?.hits ?? {}),
  ];
}

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Summary

This PR addresses a specific edge case in streaming aggregations where empty or null hits arrays could cause issues in the dashboard panel data loader. The change adds defensive null/empty checks in three critical locations within usePanelDataLoader.ts before copying search result hits when streaming aggregations are enabled.

The modifications target three different response handling scenarios:

  1. Partition-based streaming aggregations (lines 594-598) - Checks if searchRes?.data?.hits?.length > 0 before updating state.data
  2. Histogram response handling (lines 704-710) - Validates searchRes?.content?.results?.hits?.length > 0 before state updates
  3. Streaming histogram hits (lines 760-766) - Similar validation for streaming histogram data

Each check follows the same pattern: only update state.data[currentQueryIndex] when there are actual hits with content, preventing the assignment of empty arrays that could confuse the UI about loading states versus truly empty result sets. This is particularly important for real-time streaming scenarios where partial results arrive in chunks and preserving existing data until meaningful results arrive is crucial.

The change integrates well with the existing codebase's error handling patterns and maintains the streaming aggregation functionality while making it more robust against edge cases where the backend might return valid metadata but no actual data points.

Confidence score: 4/5

  • This PR is safe to merge with minimal risk as it only adds defensive checks without changing core logic
  • Score reflects simple defensive programming changes that reduce potential runtime issues without introducing complexity
  • No files require special attention as the changes are straightforward null checks with consistent patterns

1 file reviewed, 2 comments

Edit Code Review Bot Settings | Greptile

@github-actions
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Ensure hits is iterable array

Using ?? {} with the spread operator can throw at runtime because spreading a
non-iterable object into an array is invalid. Normalize hits to an array and always
assign, including empty arrays, to avoid runtime errors and stale data.

web/src/composables/dashboard/usePanelDataLoader.ts [703-710]

 if (streaming_aggs) {
-  // handle empty hits case
-  if (searchRes?.content?.results?.hits?.length > 0) {
-    state.data[payload?.meta?.currentQueryIndex] = [
-      ...(searchRes?.content?.results?.hits ?? {}),
-    ];
-  }
+  const hits = searchRes?.content?.results?.hits;
+  state.data[payload?.meta?.currentQueryIndex] = Array.isArray(hits) ? [...hits] : [];
 }
Suggestion importance[1-10]: 8

__

Why: Accurately flags a real runtime risk from spreading ?? {} and improves robustness by normalizing to an array while also preventing stale data on empty results.

Medium
Reset data on empty hits

When hits is empty but this is a streaming-aggs response, the existing data remains
stale and the UI may never clear or finalize. Explicitly reset the target state to
an empty array on empty hits to reflect the true result. This prevents showing
outdated results across streaming updates.

web/src/composables/dashboard/usePanelDataLoader.ts [593-598]

 if (res?.data?.streaming_aggs) {
-  // handle empty hits case
-  if (searchRes?.data?.hits?.length > 0) {
-    state.data[currentQueryIndex] = [...searchRes.data.hits];
-  }
+  const hits = searchRes?.data?.hits;
+  state.data[currentQueryIndex] = Array.isArray(hits) ? [...hits] : [];
 }
Suggestion importance[1-10]: 7

__

Why: Correctly identifies that skipping assignment on empty hits can leave stale UI; proposing unconditional normalization is reasonable and low-risk, though behavior change may be UX-dependent.

Medium
General
Assign even when hits empty

The conditional prevents state updates when hits is an empty array, leaving prior
data visible. For streaming updates, assign the array regardless of length to
accurately reflect cleared results. This aligns with expected behavior when a
partition yields no hits.

web/src/composables/dashboard/usePanelDataLoader.ts [703-710]

 if (streaming_aggs) {
-  // handle empty hits case
-  if (searchRes?.content?.results?.hits?.length > 0) {
-    state.data[payload?.meta?.currentQueryIndex] = [
-      ...(searchRes?.content?.results?.hits ?? {}),
-    ];
-  }
+  const hits = searchRes?.content?.results?.hits;
+  state.data[payload?.meta?.currentQueryIndex] = Array.isArray(hits) ? [...hits] : [];
 }
Suggestion importance[1-10]: 7

__

Why: Valid point about stale data due to the length > 0 guard; the proposed change is accurate and improves correctness for streaming updates, though less critical than suggestion 2.

Medium

@ktx-abhay ktx-abhay force-pushed the fix/streaming-aggs-skip-empty-hits-main branch 2 times, most recently from d1246c8 to d9e3c92 Compare September 12, 2025 10:15
@ktx-abhay ktx-abhay force-pushed the fix/streaming-aggs-skip-empty-hits-main branch from d9e3c92 to d88acf2 Compare September 12, 2025 11:22
@ktx-abhay ktx-abhay merged commit ad23d41 into main Sep 12, 2025
38 of 40 checks passed
@ktx-abhay ktx-abhay deleted the fix/streaming-aggs-skip-empty-hits-main branch September 12, 2025 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

☢️ Bug Something isn't working Review effort 2/5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants