Skip to content

fix(ui): wait for token update before calling callback#27209

Closed
chirag-madlani wants to merge 4 commits intomainfrom
fix-wait-for-token-update
Closed

fix(ui): wait for token update before calling callback#27209
chirag-madlani wants to merge 4 commits intomainfrom
fix-wait-for-token-update

Conversation

@chirag-madlani
Copy link
Copy Markdown
Collaborator

This pull request updates the token refresh logic to ensure that the new token is fully persisted before proceeding. Instead of waiting a fixed amount of time, it now explicitly waits for token persistence, which should make the refresh process more reliable.

Token refresh reliability improvement:

  • Replaced the fixed 100ms delay with a call to waitForTokenPersistence(oldToken) in TokenServiceUtil.ts, ensuring the new token is actually persisted before continuing.

Describe your changes:

Fixes

I worked on ... because ...

Type of change:

  • Bug fix
  • Improvement
  • New feature
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.

@chirag-madlani chirag-madlani requested a review from a team as a code owner April 9, 2026 12:21
Copilot AI review requested due to automatic review settings April 9, 2026 12:21
@github-actions github-actions bot added safe to test Add this label to run secure Github workflows on PRs UI UI specific issues labels Apr 9, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves frontend auth token refresh reliability by replacing a fixed post-refresh delay with a storage-polling wait, aiming to ensure the refreshed token is persisted before notifying listeners and retrying requests.

Changes:

  • Replaced the hardcoded 100ms timeout with waitForTokenPersistence(oldToken) before invoking the refresh success callback and broadcasting the tokenRefreshed storage event.
Comments suppressed due to low confidence (1)

openmetadata-ui/src/main/resources/ui/src/utils/Auth/TokenService/TokenServiceUtil.ts:103

  • waitForTokenPersistence returns after maxAttempts even if the token never changes, but refreshToken will still invoke refreshSuccessCallback and set tokenRefreshed=true. If the goal is to only notify after persistence, consider having waitForTokenPersistence return a boolean (or throw) and gate the callback/storage event on successful persistence; otherwise the PR description should be softened to indicate it's a best-effort wait.
          await this.waitForTokenPersistence(oldToken);
          this.refreshSuccessCallback?.();
          // To update all the tabs on updating channel token
          // Notify all tabs that the token has been refreshed
          localStorage.setItem(REFRESHED_KEY, 'true');

Comment on lines 96 to 100
const newToken = await this.fetchNewToken();
if (newToken) {
// Wait briefly for token to be persisted in SW+IndexedDB before notifying
await new Promise((resolve) => setTimeout(resolve, 100));
await this.waitForTokenPersistence(oldToken);
this.refreshSuccessCallback?.();
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

Existing unit tests for TokenService.refreshToken rely on advancing fake timers by 100ms; with waitForTokenPersistence polling up to 20x50ms (and requiring getOidcToken to change from oldToken), those tests will hang/fail unless they mock getOidcToken to return the updated token and advance timers accordingly. Please update/add tests to cover the new persistence-wait behavior (e.g., sequence old->new token and assert callback is invoked after persistence).

Copilot generated this review using guidance from repository custom instructions.
@@ -96,7 +96,7 @@ class TokenService {
const newToken = await this.fetchNewToken();
if (newToken) {
// Wait briefly for token to be persisted in SW+IndexedDB before notifying
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The inline comment still says "Wait briefly" even though the logic now polls storage for up to ~1s. Update the comment to reflect that we're waiting for token persistence (with a bounded timeout) rather than a fixed delay.

Suggested change
// Wait briefly for token to be persisted in SW+IndexedDB before notifying
// Wait for token persistence in SW+IndexedDB before notifying, with a bounded timeout

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 9, 2026

🟡 Playwright Results — all passed (29 flaky)

✅ 3589 passed · ❌ 0 failed · 🟡 29 flaky · ⏭️ 207 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 1 454 0 3 2
🟡 Shard 2 634 0 8 32
🟡 Shard 3 647 0 4 26
🟡 Shard 4 615 0 7 47
🟡 Shard 5 606 0 1 67
🟡 Shard 6 633 0 6 33
🟡 29 flaky test(s) (passed on retry)
  • Flow/Metric.spec.ts › Verify Related Metrics Update (shard 1, 1 retry)
  • Flow/Tour.spec.ts › Tour should work from welcome screen (shard 1, 1 retry)
  • Pages/UserCreationWithPersona.spec.ts › Create user with persona and verify on profile (shard 1, 1 retry)
  • Features/BulkEditEntity.spec.ts › Glossary (shard 2, 1 retry)
  • Features/DataQuality/BundleSuiteBulkOperations.spec.ts › Bulk selection operations (shard 2, 1 retry)
  • Features/DataQuality/TableLevelTests.spec.ts › Table Difference (shard 2, 1 retry)
  • Features/DataQuality/TestCaseImportExportBasic.spec.ts › User with EditAll on TEST_CASE resource should not be blocked from bulk edit page (shard 2, 1 retry)
  • Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts › Admin: Complete export-import-validate flow (shard 2, 1 retry)
  • Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts › EditAll User: Complete export-import-validate flow (shard 2, 1 retry)
  • Features/DataQuality/TestCaseIncidentPermissions.spec.ts › User with TEST_CASE.EDIT_ALL can see edit icon on incidents (shard 2, 1 retry)
  • Features/Glossary/GlossaryHierarchy.spec.ts › should cancel move operation (shard 2, 1 retry)
  • Features/Permissions/GlossaryPermissions.spec.ts › Team-based permissions work correctly (shard 3, 1 retry)
  • Features/RestoreEntityInheritedFields.spec.ts › Validate restore with Inherited domain and data products assigned (shard 3, 1 retry)
  • Flow/ExploreDiscovery.spec.ts › Should display deleted assets when showDeleted is checked and deleted is not present in queryFilter (shard 3, 1 retry)
  • Flow/PersonaFlow.spec.ts › Set default persona for team should work properly (shard 3, 1 retry)
  • Pages/Customproperties-part2.spec.ts › entityReferenceList shows item count, scrollable list, no expand toggle (shard 4, 1 retry)
  • Pages/DataContracts.spec.ts › Create Data Contract and validate for Table (shard 4, 1 retry)
  • Pages/DataContracts.spec.ts › Create Data Contract and validate for Topic (shard 4, 1 retry)
  • Pages/DataContractsSemanticRules.spec.ts › Validate DataProduct Rule Any_In (shard 4, 1 retry)
  • Pages/DomainUIInteractions.spec.ts › Add expert to domain via UI (shard 4, 1 retry)
  • Pages/Entity.spec.ts › Glossary Term Add, Update and Remove for child entities (shard 4, 1 retry)
  • Pages/Entity.spec.ts › Tag Add, Update and Remove for child entities (shard 4, 1 retry)
  • Pages/ExploreTree.spec.ts › Verify Database and Database Schema available in explore tree (shard 5, 1 retry)
  • Pages/InputOutputPorts.spec.ts › Input ports section collapse/expand (shard 6, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › verify create lineage for entity - Search Index (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/ProfilerConfigurationPage.spec.ts › Non admin user (shard 6, 1 retry)
  • Pages/UserDetails.spec.ts › Create team with domain and verify visibility of inherited domain in user profile after team removal (shard 6, 1 retry)
  • Pages/Users.spec.ts › Permissions for table details page for Data Consumer (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@chirag-madlani
Copy link
Copy Markdown
Collaborator Author

@copilot apply changes based on the comments in this thread

Copilot AI review requested due to automatic review settings April 9, 2026 15:12
@chirag-madlani chirag-madlani review requested due to automatic review settings April 9, 2026 15:12
Copilot AI review requested due to automatic review settings April 9, 2026 15:12
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 9, 2026

@copilot apply changes based on the comments in this thread

Applied both changes from the review thread in commit ef7ba5e:

  1. Updated the inline comment to accurately describe the bounded-timeout polling behavior: // Wait for token persistence in SW+IndexedDB before notifying, with a bounded timeout

  2. Updated and expanded the refreshToken tests:

    • Updated should refresh token if expired to mock getOidcToken returning 'old-token' first then 'new-token' (simulating persistence), and replaced the manual jest.advanceTimersByTime(100) with jest.runAllTimersAsync() to correctly advance through the polling loop
    • Added should invoke refreshSuccessCallback after token persistence is confirmed — verifies callback is called once the new token appears in storage
    • Added should invoke callback after bounded timeout even if token is never updated in storage — verifies callback is still called after all 20 polling attempts are exhausted

@gitar-bot
Copy link
Copy Markdown

gitar-bot bot commented Apr 9, 2026

Code Review ✅ Approved

Fixes a race condition in the UI token handling by ensuring the token update completes before invoking the callback. No issues found.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

openmetadata-ui/src/main/resources/ui/src/utils/Auth/TokenService/TokenServiceUtil.ts:104

  • fetchNewToken() clears the refreshInProgress flag (in its finally) before this new waitForTokenPersistence(...) completes. This expands the window where other tabs can see no refresh in progress and start their own refresh while the token is still being persisted. To avoid duplicate refreshes/races, consider only clearing refreshInProgress after persistence is confirmed (or after the bounded wait) and notifications are sent.
        const newToken = await this.fetchNewToken();
        if (newToken) {
          // Wait for token persistence in SW+IndexedDB before notifying, with a bounded timeout
          await this.waitForTokenPersistence(oldToken);
          this.refreshSuccessCallback?.();
          // To update all the tabs on updating channel token
          // Notify all tabs that the token has been refreshed
          localStorage.setItem(REFRESHED_KEY, 'true');
        }

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 9, 2026

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 64%
64.2% (59603/92836) 43.75% (31073/71021) 46.89% (9372/19983)

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 9, 2026

@chirag-madlani
Copy link
Copy Markdown
Collaborator Author

Covered with #27214

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 UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants