Skip to content

CONSOLE-5066: Refactor ResourceEventStream for Performance and Impersonation Support#16027

Open
krishagarwal278 wants to merge 1 commit intoopenshift:mainfrom
krishagarwal278:CONSOLE-5066
Open

CONSOLE-5066: Refactor ResourceEventStream for Performance and Impersonation Support#16027
krishagarwal278 wants to merge 1 commit intoopenshift:mainfrom
krishagarwal278:CONSOLE-5066

Conversation

@krishagarwal278
Copy link
Member

@krishagarwal278 krishagarwal278 commented Feb 13, 2026

Summary: Refactored the ResourceEventStream component to use standard Kubernetes watch hooks so that we reduce API server load and correctly support user impersonation. Replaced the custom WebSocket logic with the useK8sWatchResource hook.

Reviewer's Checklist:

  • The component no longer receives all cluster events as "added" messages upon every page load.
  • Event streams work correctly when the Console is used in impersonation mode.
  • The implementation leverages useK8sWatchResource instead of custom WebSocket code.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved event loading and error messaging with enhanced status feedback during data retrieval.
    • Better error state visualization when events fail to load.
  • Refactor

    • Restructured event data fetching mechanism for improved reliability and consistency.
    • Streamlined event processing pipeline for clearer data flow and filtering logic.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Feb 13, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 13, 2026

@krishagarwal278: This pull request references CONSOLE-5066 which is a valid jira issue.

Details

In response to this:

Summary: Refactored the ResourceEventStream component to use standard Kubernetes watch hooks so that we reduce API server load and correctly support user impersonation. Replaced the custom WebSocket logic with the useK8sWatchResource hook.

Reviewer's Checklist:

  • The component no longer receives all cluster events as "added" messages upon every page load.
  • Event streams work correctly when the Console is used in impersonation mode.
  • The implementation leverages useK8sWatchResource instead of custom WebSocket code.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot requested review from Leo6Leo and sg00dwin February 13, 2026 21:37
@openshift-ci openshift-ci bot added the component/core Related to console core functionality label Feb 13, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 13, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: krishagarwal278
Once this PR has been reviewed and has the lgtm label, please assign cajieh for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 13, 2026

@krishagarwal278: This pull request references CONSOLE-5066 which is a valid jira issue.

Details

In response to this:

Summary: Refactored the ResourceEventStream component to use standard Kubernetes watch hooks so that we reduce API server load and correctly support user impersonation. Replaced the custom WebSocket logic with the useK8sWatchResource hook.

Reviewer's Checklist:

  • The component no longer receives all cluster events as "added" messages upon every page load.
  • Event streams work correctly when the Console is used in impersonation mode.
  • The implementation leverages useK8sWatchResource instead of custom WebSocket code.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

  • Improved event loading and error messaging with enhanced status feedback during data retrieval.

  • Better error state visualization when events fail to load.

  • Refactor

  • Restructured event data fetching mechanism for improved reliability and consistency.

  • Streamlined event processing pipeline for clearer data flow and filtering logic.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

Walkthrough

The events component migrates from websocket-driven in-memory streaming (WSFactory, watchURL) to the standard Kubernetes watch hook (useK8sWatchResource). The new implementation establishes a data pipeline: fetch EventKind[] with explicit loading and error states, compute sorted events via sortEvents, then derive filtered events by applying kind, type, and text filters. UI rendering shifts from state-based to data-driven using eventsLoaded and eventsLoadError flags. Websocket lifecycle management, configuration, and local state mutations are removed. Public component signatures remain unchanged while the underlying data flow transitions to Kubernetes list-then-watch semantics.

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (100 files):

⚔️ .coderabbit.yaml (content)
⚔️ .cursor/context.md (content)
⚔️ .cursor/context.md~HEAD (content)
⚔️ AGENTS.md (content)
⚔️ ARCHITECTURE.md (content)
⚔️ CLAUDE.md (content)
⚔️ CLAUDE.md~HEAD (content)
⚔️ CONTRIBUTING.md (content)
⚔️ STYLEGUIDE.md (content)
⚔️ frontend/.vscode/settings.json (content)
⚔️ frontend/get-local-plugins.js (content)
⚔️ frontend/package.json (content)
⚔️ frontend/packages/console-app/locales/en/console-app.json (content)
⚔️ frontend/packages/console-app/src/__tests__/extension-checks/nav-items.spec.ts (content)
⚔️ frontend/packages/console-app/src/__tests__/extension-checks/perspectives.spec.ts (content)
⚔️ frontend/packages/console-app/src/__tests__/extension-checks/yaml-templates.spec.ts (content)
⚔️ frontend/packages/console-app/src/__tests__/hooks/useCSPViolationDetector.spec.tsx (content)
⚔️ frontend/packages/console-app/src/actions/hooks/useCommonActions.ts (content)
⚔️ frontend/packages/console-app/src/components/data-view/ConsoleDataView.tsx (content)
⚔️ frontend/packages/console-app/src/components/pdb/PDBFormPage.tsx (content)
⚔️ frontend/packages/console-dynamic-plugin-sdk/scripts/utils/type-resolver.ts (content)
⚔️ frontend/packages/console-dynamic-plugin-sdk/src/runtime/plugin-init.ts (content)
⚔️ frontend/packages/console-dynamic-plugin-sdk/src/webpack/ConsoleRemotePlugin.ts (content)
⚔️ frontend/packages/console-plugin-sdk/src/codegen/__tests__/local-plugins.spec.ts (content)
⚔️ frontend/packages/console-plugin-sdk/src/codegen/local-plugins.ts (content)
⚔️ frontend/packages/console-shared/locales/en/console-shared.json (content)
⚔️ frontend/packages/console-shared/src/components/alerts/SwitchToYAMLAlert.tsx (content)
⚔️ frontend/packages/console-shared/src/components/dashboard/status-card/OperatorStatusBody.tsx (content)
⚔️ frontend/packages/console-shared/src/components/datetime/__tests__/Timestamp.spec.tsx (content)
⚔️ frontend/packages/console-shared/src/components/error/fallbacks/ErrorBoundaryFallbackPage.tsx (content)
⚔️ frontend/packages/console-shared/src/components/formik-fields/CodeEditorField.tsx (content)
⚔️ frontend/packages/console-shared/src/components/formik-fields/field-types.ts (content)
⚔️ frontend/packages/console-shared/src/components/modals/ErrorDetailsModal.tsx (content)
⚔️ frontend/packages/console-shared/src/components/synced-editor/index.tsx (content)
⚔️ frontend/packages/console-shared/src/components/utils/index.ts (content)
⚔️ frontend/packages/console-shared/src/hooks/index.ts (content)
⚔️ frontend/packages/console-shared/src/hooks/version.ts (content)
⚔️ frontend/packages/dev-console/locales/en/devconsole.json (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/__tests__/BuildConfigFormPage.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/EnvironmentVariablesSection.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/HooksSection.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/ImagesSection.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/NameSection.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/PolicySection.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/SecretsSection.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/SourceSection.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/TriggersSection.spec.tsx (content)
⚔️ frontend/packages/dev-console/src/components/import/__tests__/import-submit-utils.spec.ts (content)
⚔️ frontend/packages/dev-console/src/components/import/__tests__/upload-jar-submit-utils.spec.ts (content)
⚔️ frontend/packages/dev-console/src/components/import/icon/CustomIconModal.tsx (content)
⚔️ frontend/packages/dev-console/src/components/import/import-types.ts (content)
⚔️ frontend/packages/dev-console/src/components/pipeline-section/pipeline/__tests__/pipeline-template-utils.spec.ts (content)
⚔️ frontend/packages/dev-console/src/components/pipeline-section/pipeline/pipeline-template-utils.ts (content)
⚔️ frontend/packages/knative-plugin/src/components/pub-sub/PubSubController.tsx (content)
⚔️ frontend/packages/knative-plugin/src/components/pub-sub/PubSubModalLauncher.ts (content)
⚔️ frontend/packages/knative-plugin/src/topology/components/knativeComponentUtils.ts (content)
⚔️ frontend/packages/knative-plugin/src/topology/create-connector-utils.ts (content)
⚔️ frontend/packages/metal3-plugin/src/components/baremetal-hosts/host-actions-provider.ts (content)
⚔️ frontend/packages/operator-lifecycle-manager-v1/locales/en/olm-v1.json (content)
⚔️ frontend/packages/operator-lifecycle-manager-v1/src/components/cluster-extension/CreateClusterExtension.tsx (content)
⚔️ frontend/packages/operator-lifecycle-manager-v1/src/const.ts (content)
⚔️ frontend/packages/operator-lifecycle-manager/src/actions/useDefaultOperandActions.ts (content)
⚔️ frontend/packages/operator-lifecycle-manager/src/actions/useOperatorActions.ts (content)
⚔️ frontend/packages/operator-lifecycle-manager/src/components/operand/create-operand.tsx (content)
⚔️ frontend/packages/shipwright-plugin/src/components/logs/logs-utils.ts (content)
⚔️ frontend/packages/topology/locales/en/topology.json (content)
⚔️ frontend/packages/topology/src/actions/edgeActions.ts (content)
⚔️ frontend/packages/topology/src/components/export-app/__tests__/ExportViewLogButton.spec.tsx (content)
⚔️ frontend/packages/topology/src/components/graph-view/Topology.tsx (content)
⚔️ frontend/packages/topology/src/components/graph-view/components/componentUtils.ts (content)
⚔️ frontend/packages/topology/src/utils/moveNodeToGroup.tsx (content)
⚔️ frontend/public/components/__tests__/create-yaml.spec.tsx (content)
⚔️ frontend/public/components/app-contents.tsx (content)
⚔️ frontend/public/components/app.tsx (content)
⚔️ frontend/public/components/create-resource.tsx (content)
⚔️ frontend/public/components/create-yaml.tsx (content)
⚔️ frontend/public/components/dashboard/dashboards-page/cluster-dashboard/health-item.tsx (content)
⚔️ frontend/public/components/debug-terminal.tsx (content)
⚔️ frontend/public/components/droppable-edit-yaml.tsx (content)
⚔️ frontend/public/components/edit-yaml.tsx (content)
⚔️ frontend/public/components/events.tsx (content)
⚔️ frontend/public/components/filter-toolbar.tsx (content)
⚔️ frontend/public/components/graphs/__tests__/prometheus-graph.spec.tsx (content)
⚔️ frontend/public/components/import-yaml.tsx (content)
⚔️ frontend/public/components/modals/alert-routing-modal.tsx (content)
⚔️ frontend/public/components/modals/column-management-modal.tsx (content)
⚔️ frontend/public/components/modals/delete-modal.tsx (content)
⚔️ frontend/public/components/modals/error-modal.tsx (content)
⚔️ frontend/public/components/modals/index.ts (content)
⚔️ frontend/public/components/modals/labels-modal.tsx (content)
⚔️ frontend/public/components/modals/tags.tsx (content)
⚔️ frontend/public/components/monitoring/alertmanager/alertmanager-config.tsx (content)
⚔️ frontend/public/components/pod.tsx (content)
⚔️ frontend/public/components/storage/attach-storage.tsx (content)
⚔️ frontend/public/components/utils/__tests__/async.spec.tsx (content)
⚔️ frontend/public/components/utils/async.tsx (content)
⚔️ frontend/public/locales/en/public.json (content)
⚔️ frontend/public/plugins.ts (content)
⚔️ frontend/public/style/_overrides.scss (content)
⚔️ frontend/scripts/jest-transform-graphql.js (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: refactoring ResourceEventStream to use Kubernetes watch hooks instead of custom WebSocket logic, directly supporting the stated goals of performance improvement and impersonation support.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch CONSOLE-5066
  • Post resolved changes as copyable diffs in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@frontend/public/components/events.tsx`:
- Around line 392-399: The pause toggle no longer stops updates because
useK8sWatchResource keeps fetching; either remove the toggle UI or implement
client-side freezing: when toggling to paused (active false) capture a snapshot
(e.g., pausedEvents state) from eventsData and have sortedEvents derive from
pausedEvents when active is false and from eventsData when active is true;
update toggleStream to set active and populate/clear pausedEvents accordingly,
keep using sortEvents(...).slice(0, maxMessages) on the chosen source
(eventsData or pausedEvents) so the visible list stops changing while paused.
🧹 Nitpick comments (2)
frontend/public/components/events.tsx (2)

401-403: Redundant .slice(0, maxMessages) call.

sortedEvents is already limited to maxMessages (line 398), and filterEvents can only reduce the count. The second slice is always a no-op.

♻️ Remove redundant slice
  const filteredEvents = useMemo(() => {
-   return filterEvents(sortedEvents, { kind, type, filter, textFilter }).slice(0, maxMessages);
+   return filterEvents(sortedEvents, { kind, type, filter, textFilter });
  }, [sortedEvents, kind, type, filter, textFilter]);

423-437: Terminology inconsistency with new implementation.

The status messages reference "stream" terminology ("Error connecting to event stream", "Streaming events..."), but the implementation now uses list-then-watch semantics rather than true streaming. Consider updating for accuracy:

📝 Update status text to reflect list-then-watch
  if (eventsLoadError) {
    statusBtnTxt = (
      <span className="co-sysevent-stream__connection-error">
-       {t('Error connecting to event stream')}
+       {t('Error loading events')}
      </span>
    );
    sysEventStatus = <ErrorLoadingEvents />;
  } else if (!eventsLoaded) {
    statusBtnTxt = <span>{t('Loading events...')}</span>;
    sysEventStatus = <Loading />;
  } else if (active) {
-   statusBtnTxt = <span>{t('Streaming events...')}</span>;
+   statusBtnTxt = <span>{t('Watching for events...')}</span>;
  } else {
-   statusBtnTxt = <span>{t('Event stream is paused.')}</span>;
+   statusBtnTxt = <span>{t('Event updates paused.')}</span>;
  }

Note: If you keep the pause toggle, ensure the i18n keys are updated in the translation files as well.

Comment on lines +392 to +399
// Sort events and limit to maxMessages
// Note: We keep the events visible even when paused (active=false)
const sortedEvents = useMemo(() => {
if (!eventsData) {
return [];
}
return () => {
ws.current?.destroy();
};
}, [namespace, fieldSelector, mock, t]);
return sortEvents(eventsData).slice(0, maxMessages);
}, [eventsData]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Pause/play toggle no longer controls data updates.

The active state and toggleStream function remain, but with useK8sWatchResource, the watch continues fetching updates regardless of the toggle state. Previously with WebSocket, pausing would stop receiving new events. Now, the "pause" button only changes the status text—the underlying data continues to update in the background.

This is a behavioral change that may confuse users who expect pausing to freeze the event list. Consider one of:

  1. Remove the toggle entirely if pause functionality isn't meaningful with list-then-watch semantics.
  2. Implement client-side freezing by capturing a snapshot of eventsData when paused:
🔧 Option 2: Client-side pause implementation
+ const [pausedSnapshot, setPausedSnapshot] = useState<EventKind[] | null>(null);
+
+ const toggleStream = () => {
+   setActive((prev) => {
+     const newActive = !prev;
+     if (!newActive) {
+       // Capture snapshot when pausing
+       setPausedSnapshot(eventsData ?? []);
+     } else {
+       // Clear snapshot when resuming
+       setPausedSnapshot(null);
+     }
+     return newActive;
+   });
+ };

  // Sort events and limit to maxMessages
- // Note: We keep the events visible even when paused (active=false)
  const sortedEvents = useMemo(() => {
-   if (!eventsData) {
+   const dataSource = pausedSnapshot ?? eventsData;
+   if (!dataSource) {
      return [];
    }
-   return sortEvents(eventsData).slice(0, maxMessages);
- }, [eventsData]);
+   return sortEvents(dataSource).slice(0, maxMessages);
+ }, [pausedSnapshot, eventsData]);

Also applies to: 405-407

🤖 Prompt for AI Agents
In `@frontend/public/components/events.tsx` around lines 392 - 399, The pause
toggle no longer stops updates because useK8sWatchResource keeps fetching;
either remove the toggle UI or implement client-side freezing: when toggling to
paused (active false) capture a snapshot (e.g., pausedEvents state) from
eventsData and have sortedEvents derive from pausedEvents when active is false
and from eventsData when active is true; update toggleStream to set active and
populate/clear pausedEvents accordingly, keep using sortEvents(...).slice(0,
maxMessages) on the chosen source (eventsData or pausedEvents) so the visible
list stops changing while paused.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 14, 2026

@krishagarwal278: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/frontend f9e3a51 link true /test frontend

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/core Related to console core functionality jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants