Skip to content

perf(ui): lazy load service and ingestion widgets#29182

Open
shah-harshit wants to merge 3 commits into
feat/dashboard-lcp-parentfrom
feat/dashboard-lcp-06-services
Open

perf(ui): lazy load service and ingestion widgets#29182
shah-harshit wants to merge 3 commits into
feat/dashboard-lcp-parentfrom
feat/dashboard-lcp-06-services

Conversation

@shah-harshit

@shah-harshit shah-harshit commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Lazy-loads service insight/metadata agent widgets and removes eager service/ingestion utility imports from shared paths.
  • Split from the dashboard LCP optimization work so it can be reviewed independently.

Testing

  • Not run; tests will be fixed separately for this PR.

Ref: https://github.com/open-metadata/openmetadata-collate/issues/4230


Summary by Gitar

  • Performance optimizations:
    • Implemented LRU caching for user profiles in userAPI.ts to reduce redundant API calls across widgets.
    • Added clearUserProfileCache and clearDashboardWidgetCache to the authentication logout flow.
    • Lazy-loaded PageNotFound, LogoutPage, and other core routes in AuthenticatedRoutes.tsx.
    • Deferred oidc-client loading in AuthProvider.util.ts to improve initial load time.
  • UI/UX improvements:
    • Introduced withSuspenseFallback for critical UI components to handle lazy-loading states gracefully.
    • Decoupled ServiceUtilClassBase from eager imports by centralizing widget access via ServiceInsightsWidgets.tsx.

This will update automatically on new commits.

Greptile Summary

This PR decouples eager service/ingestion widget imports from shared module paths to reduce the initial bundle size, and defers oidc-client loading to the SSO test-login flow only. It is part of a larger dashboard LCP optimization effort.

  • Lazy widgets: AgentsStatusWidget, PlatformInsightsWidget, TotalDataAssetsWidget, and MetadataAgentsWidget sub-components (IngestionListTable, AddIngestionButton) are now wrapped with withSuspenseFallback(lazy(...)) and exported via ServiceInsightsWidgets.tsx, removing them from the eager import chain in ServiceUtilClassBase.
  • Async OIDC deferred: getCandidateUserManagerConfig is made async and dynamically imports WebStorageStateStore on demand; both call-sites (ssoTestCallbackBootstrap.ts, useSsoTestLogin.ts) are correctly updated with await.
  • Base-class cleanup: ServiceUtilClassBase.getAgentsTabWidgets() now returns {}, reflecting that the default MetadataAgentsWidget is provided via getDefaultAgentsTabWidgets() consumed directly by Ingestion.component.tsx, keeping the base class free of heavy widget imports.

Confidence Score: 5/5

Safe to merge — all widget imports are correctly deferred, the async OIDC change is properly awaited at every call-site, and base-class API changes are consistent with how callers already consume the defaults.

The PR performs purely structural refactoring: moving eager imports to dynamic chunks and converting runtime imports to type-only imports where the value is never instantiated. The async signature change to getCandidateUserManagerConfig is propagated to both callers. ServiceUtilClassBase.getAgentsTabWidgets() returning {} is intentional because Ingestion.component.tsx already calls getDefaultAgentsTabWidgets() directly for the default widget. No logic paths are altered in a way that could produce incorrect behavior.

No files require special attention. The most structurally significant change is ServiceUtilClassBase.ts — its getAgentsTabWidgets() now returns an empty object — but this is intentional and consistent with how Ingestion.component.tsx sources its default widget.

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsWidgets.tsx Adds lazy-loaded AgentsStatusWidget, PlatformInsightsWidget, and TotalDataAssetsWidget via withSuspenseFallback(React.lazy(...)) and exports them through getDefaultInsightsTabWidgets(); type-only imports for prop interfaces are correctly used.
openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtilClassBase.ts Removes four eager widget imports, delegates getInsightsTabWidgets to getDefaultInsightsTabWidgets(), and makes getAgentsTabWidgets() return {} — the default MetadataAgentsWidget is now supplied directly by Ingestion.component.tsx via getDefaultAgentsTabWidgets().
openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider.util.ts Makes getCandidateUserManagerConfig async with a dynamic import of oidc-client to defer the vendor chunk; WebStorageStateStore top-level import is correctly demoted to import type.
openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedRoutes.tsx Converts five route-level page imports to withSuspenseFallback(lazy(...)) to split them into separate chunks.
openmetadata-ui/src/main/resources/ui/src/components/Settings/Services/Ingestion/MetadataAgentsWidget/MetadataAgentsWidget.tsx Lazy-loads IngestionListTable and AddIngestionButton sub-components via withSuspenseFallback(lazy(...)), removing them from the widget's eager bundle.
openmetadata-ui/src/main/resources/ui/src/App.tsx Removes the idlePrefetchRoutes call and its useEffect, simplifying app bootstrap.
openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx Changes WebStorageStateStore import to import type since it is only used in a type assertion, not instantiated directly in this file.
openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/LazyAuthProviderWrappers.tsx Changes CacheLocation import to import type, removing the runtime side-effect of loading the Auth0 SDK just for a type reference.
openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts Changes DataQualityPageTabs import to import type, removing the runtime dependency on DataQualityPage.interface in the router utility.
openmetadata-ui/src/main/resources/ui/src/components/SettingsSso/SsoTestLogin/ssoTestCallbackBootstrap.ts Correctly adds await before getCandidateUserManagerConfig to handle the newly async function.
openmetadata-ui/src/main/resources/ui/src/components/SettingsSso/SsoTestLogin/useSsoTestLogin.ts Correctly adds await before getCandidateUserManagerConfig to handle the newly async function.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[App Bootstrap] --> B[AuthProvider]
    A --> C[AuthenticatedRoutes]

    B --> D{OIDC flow?}
    D -- SSO Test Login only --> E["dynamic import oidc-client\ngetCandidateUserManagerConfig async"]
    D -- Normal login --> F[OidcTokenStorage lightweight]

    C --> G[withSuspenseFallback + lazy]
    G --> H[PageNotFound chunk]
    G --> I[LogoutPage chunk]
    G --> J[AccessNotAllowedPage chunk]

    M[ServiceUtilClassBase] --> N[getInsightsTabWidgets]
    N --> O[getDefaultInsightsTabWidgets]
    O --> P[withSuspenseFallback + lazy]
    P --> Q[AgentsStatusWidget chunk]
    P --> R[PlatformInsightsWidget chunk]
    P --> S[TotalDataAssetsWidget chunk]

    T[Ingestion.component] --> U[getDefaultAgentsTabWidgets]
    T --> V["getAgentsTabWidgets returns empty\nextension point for subclasses"]
    U --> W[MetadataAgentsWidget chunk]
    W --> X[withSuspenseFallback + lazy]
    X --> Y[IngestionListTable chunk]
    X --> Z[AddIngestionButton chunk]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[App Bootstrap] --> B[AuthProvider]
    A --> C[AuthenticatedRoutes]

    B --> D{OIDC flow?}
    D -- SSO Test Login only --> E["dynamic import oidc-client\ngetCandidateUserManagerConfig async"]
    D -- Normal login --> F[OidcTokenStorage lightweight]

    C --> G[withSuspenseFallback + lazy]
    G --> H[PageNotFound chunk]
    G --> I[LogoutPage chunk]
    G --> J[AccessNotAllowedPage chunk]

    M[ServiceUtilClassBase] --> N[getInsightsTabWidgets]
    N --> O[getDefaultInsightsTabWidgets]
    O --> P[withSuspenseFallback + lazy]
    P --> Q[AgentsStatusWidget chunk]
    P --> R[PlatformInsightsWidget chunk]
    P --> S[TotalDataAssetsWidget chunk]

    T[Ingestion.component] --> U[getDefaultAgentsTabWidgets]
    T --> V["getAgentsTabWidgets returns empty\nextension point for subclasses"]
    U --> W[MetadataAgentsWidget chunk]
    W --> X[withSuspenseFallback + lazy]
    X --> Y[IngestionListTable chunk]
    X --> Z[AddIngestionButton chunk]
Loading

Reviews (3): Last reviewed commit: "fix(ui): resolve services ingestion lazy..." | Re-trigger Greptile

@shah-harshit shah-harshit requested a review from a team as a code owner June 18, 2026 10:32
@shah-harshit shah-harshit added UI UI specific issues safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check labels Jun 18, 2026
@shah-harshit shah-harshit self-assigned this Jun 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

Comment thread openmetadata-ui/src/main/resources/ui/src/rest/userAPI.ts Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/rest/userAPI.ts Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/rest/userAPI.ts Outdated
@shah-harshit shah-harshit changed the base branch from main to feat/dashboard-lcp-parent June 18, 2026 10:59
@gitar-bot

gitar-bot Bot commented Jun 18, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 2 resolved / 2 findings

Implements lazy-loading for service widgets and auth-related routes to improve LCP, while cleaning up dead idlePrefetchRoutes.ts code and resolving potential import issues. No findings remain.

✅ 2 resolved
Edge Case: getUserByName profile cache keyed only by name, ignores params

📄 openmetadata-ui/src/main/resources/ui/src/rest/userAPI.ts:98-112
getUserByName caches and de-dupes the profile request using only name as the key (userProfileCache.get(name) / userProfileRequests.get(name)), but the request also depends on params (e.g. include for deleted/non-deleted, or any additional fields beyond profile). The cache branch is only entered when params.fields === TabSpecificField.PROFILE, but two callers could still pass different include values (e.g. Include.All vs Include.NonDeleted) while both having fields=profile; the second caller would receive the first caller's cached object, which may not match its include filter. Consider incorporating the relevant params (at minimum include) into the cache key, or document that only the exact fields=profile shape is ever requested so the assumption is safe.

Bug: Imports reference modules/symbols that don't exist in this branch

📄 openmetadata-ui/src/main/resources/ui/src/rest/userAPI.ts:18 📄 openmetadata-ui/src/main/resources/ui/src/rest/userAPI.ts:28 📄 openmetadata-ui/src/main/resources/ui/src/rest/userAPI.ts:33 📄 openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx:56 📄 openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx:84 📄 openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx:240-242
This PR adds imports for four modules/symbols that do not exist anywhere in the branch, which will break the TypeScript build and the runtime bundle:

  1. userAPI.ts:18import { MAX_USER_PROFILE_CACHE_ENTRIES } from '../constants/DashboardCache.constants'; — file DashboardCache.constants.ts does not exist (only Dashboard.constants.ts).
  2. userAPI.ts:28import { makeLruCache } from '../utils/lruCacheUtils';lruCacheUtils.ts does not exist; makeLruCache is referenced only here.
  3. AuthProvider.tsx:56import { clearDashboardWidgetCache } from '../../../hooks/useDashboardWidgetData'; — the useDashboardWidgetData hook file does not exist.
  4. AuthProvider.tsx:84import { clearActivityFeedCache } from '../../ActivityFeed/ActivityFeedProvider/ActivityFeedCache';ActivityFeedCache.ts does not exist in ActivityFeedProvider/.

I verified via Glob/Grep that none of these files/symbols are present and that the only references are the new imports added here. The PR description notes it was "split from the dashboard LCP optimization work," so the providing modules were likely left in the other PR. Combined with the skip-pr-checks label, this would merge a branch that fails to compile.

Fix: include the source files (lruCacheUtils.ts, DashboardCache.constants.ts, useDashboardWidgetData.ts, ActivityFeedCache.ts with their exports) in this PR, or rebase it onto the branch/PR that introduces them so the dependencies land first.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@github-actions

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 62%
62.23% (66537/106904) 44.03% (37258/84607) 45.37% (11193/24670)

@sonarqubecloud

Copy link
Copy Markdown

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

Labels

safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant