Skip to content

feat(frontend): detect new deployment and prompt to reload#5849

Open
Ma77Ball wants to merge 18 commits into
apache:mainfrom
Ma77Ball:feat/deployment-version-check
Open

feat(frontend): detect new deployment and prompt to reload#5849
Ma77Ball wants to merge 18 commits into
apache:mainfrom
Ma77Ball:feat/deployment-version-check

Conversation

@Ma77Ball

@Ma77Ball Ma77Ball commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

  • Add DeploymentVersionService (provided in root): checkForUpdate() fetches a cache-busted /assets/version.json and reports true only when its buildNumber is a non-empty string that differs from the compiled Version.buildNumber; start() polls every 5 minutes and, on the first detected change, shows one sticky dismissible notification (NotificationService.blank with nzDuration 0) asking the user to refresh.
  • Extend build-version.js to also emit src/assets/version.json ({buildNumber, version}) alongside version.prod.ts (gitignored, regenerated per build).
  • Wire the poll in AppComponent, skipped when Version.buildNumber is the "dev" placeholder so dev/test builds do not poll.
  • Malformed manifests (missing, empty, non-string buildNumber, null body) and transport failures (network error, 404, 500) are treated as "no update" so a bad manifest never triggers a false prompt.
image

Any related issues, documentation, discussions?

Closes: #5836

How was this PR tested?

  • Run yarn test --include='**/deployment-version.service.spec.ts' from frontend/, expect 15 passing cases: update detected (differing build), no update (same build), malformed manifests (missing/empty/non-string buildNumber, null body), transport failures (network error, 404, 500), the request carries a cache-busting query param, promptReload shows exactly one sticky notification, and the polling path prompts once on update, never prompts while unchanged, and stops after the first update.
  • Manual: build the frontend (yarn build) and confirm dist/assets/version.json exists with the build number; serve it, then replace version.json with a different buildNumber and within the poll interval expect a single "New version available" notification; reload clears it.

Was this PR authored or co-authored using generative AI tooling?

Co-authored with Claude Opus 4.8 in compliance with ASF

@github-actions github-actions Bot added feature frontend Changes related to the frontend GUI labels Jun 21, 2026
@aglinxinyuan

Copy link
Copy Markdown
Contributor

I feel this PR may be over-engineering a relatively small and infrequent issue.

@codecov-commenter

codecov-commenter commented Jun 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.17073% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.23%. Comparing base (7944c09) to head (b2f672e).

Files with missing lines Patch % Lines
frontend/build-version.js 45.45% 6 Missing ⚠️
...la/org/apache/texera/common/config/GuiConfig.scala 0.00% 2 Missing ⚠️
...ommon/service/notification/notification.service.ts 0.00% 2 Missing ⚠️
...e/deployment-version/deployment-version.service.ts 94.73% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #5849      +/-   ##
============================================
- Coverage     55.25%   55.23%   -0.02%     
+ Complexity     2993     2986       -7     
============================================
  Files          1117     1120       +3     
  Lines         43195    43252      +57     
  Branches       4657     4660       +3     
============================================
+ Hits          23866    23892      +26     
- Misses        17930    17957      +27     
- Partials       1399     1403       +4     
Flag Coverage Δ *Carryforward flag
access-control-service 70.00% <ø> (ø)
agent-service 34.36% <ø> (ø) Carriedforward from dc33251
amber 57.75% <0.00%> (-0.07%) ⬇️
computing-unit-managing-service 0.00% <ø> (ø)
config-service 52.30% <100.00%> (+0.74%) ⬆️
file-service 59.02% <ø> (ø)
frontend 48.82% <76.31%> (+0.06%) ⬆️
notebook-migration-service 78.57% <ø> (ø)
pyamber 90.20% <ø> (ø) Carriedforward from dc33251
python 90.76% <ø> (ø) Carriedforward from dc33251
workflow-compiling-service 55.14% <ø> (ø)

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Ma77Ball

Ma77Ball commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

@aglinxinyuan Fair point, but the issue isn't cosmetic:

  • We ship JS bundles with hashed filenames, so after a deploy, open tabs reference old files that no longer exist.
  • Navigating then 404s and breaks the page (usually a blank screen). Since people keep tabs open for hours, this hits after most releases.
  • This PR just shows a one-click "refresh to update" message instead.

It's also lightweight: one small service that polls a static version.json every 5 min, does nothing on dev builds, and prompts at most once, with no backend or new infra.

Happy to scale it back if you'd prefer (e.g. check only on navigation, or behind a config flag).

@Ma77Ball Ma77Ball force-pushed the feat/deployment-version-check branch from 60be3aa to 0317dce Compare June 21, 2026 08:59
@Ma77Ball Ma77Ball marked this pull request as ready for review June 21, 2026 09:06
@Ma77Ball

Copy link
Copy Markdown
Contributor Author

/request-review @aglinxinyuan

@github-actions github-actions Bot requested a review from aglinxinyuan June 21, 2026 09:32
@Yicong-Huang

Copy link
Copy Markdown
Contributor

@Ma77Ball please include a UI screenshot/gif for this feature. Thanks!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a frontend mechanism to detect when a newer deployment is available (via a generated assets/version.json) and prompts the user to reload, reducing the chance of running an outdated bundle after a deploy.

Changes:

  • Generate a runtime-readable deployment manifest (src/assets/version.json) alongside version.prod.ts during yarn build via build-version.js.
  • Add DeploymentVersionService to poll assets/version.json and show a sticky notification once a new build is detected.
  • Wire polling startup in AppComponent (guarded to skip "dev" builds) and add unit tests for the build artifact generator, the service, and the AppComponent wiring.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
frontend/src/build-version.spec.ts Adds tests for renderVersionArtifacts (TS module + manifest JSON generation and escaping).
frontend/src/app/common/service/deployment-version/deployment-version.service.ts New service that polls assets/version.json and prompts once on mismatch with compiled build number.
frontend/src/app/common/service/deployment-version/deployment-version.service.spec.ts Unit tests covering update detection, malformed/failed fetches, cache-busting, and polling behavior.
frontend/src/app/app.component.ts Starts deployment polling on app bootstrap when not in "dev" build.
frontend/src/app/app.component.spec.ts Adds tests for config-loaded detection, polling guard, and retry reload behavior.
frontend/build-version.js Extends build step to emit src/assets/version.json and exports a testable artifact renderer.
frontend/build-version.d.ts Provides TypeScript typings for build-version.js exports used in tests.
frontend/.gitignore Ignores generated src/assets/version.json.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frontend/src/app/app.component.spec.ts
@Yicong-Huang

Copy link
Copy Markdown
Contributor

To reply @aglinxinyuan, I somewhat think this might be a good feature to include, but would love to see the frontend experience to decide.

@Ma77Ball it may be a good idea to have a config to turn off by default. We could try it with one specific deployment later.

@Ma77Ball

Copy link
Copy Markdown
Contributor Author

@Yicong-Huang Added deploymentVersionCheckEnabled, off by default. Polling only runs when a deployment opts in. Screenshot/gif coming shortly.

@Ma77Ball

Copy link
Copy Markdown
Contributor Author

@aglinxinyuan It's now behind a flag that's off by default, so no change unless a deployment opts in.

@github-actions github-actions Bot added common platform Non-amber Scala service paths labels Jun 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @zyratlo, @aglinxinyuan
    You can notify them by mentioning @zyratlo, @aglinxinyuan in a comment.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

⚠️ Benchmark changes need a look

🟢 2 better · 🔴 2 worse · ⚪ 11 noise (<±5%) · 0 without baseline

Compared against main 7944c09 benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

config throughput MB/s latency max Δ latest / 7d
🔴 bs=10 sw=10 sl=64 406 0.248 24,243/33,673/33,673 us 🔴 +7.9% / 🔴 +117.8%
🟢 bs=100 sw=10 sl=64 793 0.484 125,962/137,936/137,936 us 🟢 -9.9% / 🔴 +25.3%
bs=1000 sw=10 sl=64 932 0.569 1,075,477/1,134,053/1,134,053 us ⚪ within ±5% / 🔴 +7.4%
Baseline details

Latest main 7944c09 from same runner

config metric PR latest main 7d avg Δ latest Δ 7d
bs=10 sw=10 sl=64 throughput 406 tuples/sec 413 tuples/sec 756.6 tuples/sec -1.7% -46.3%
bs=10 sw=10 sl=64 MB/s 0.248 MB/s 0.252 MB/s 0.462 MB/s -1.6% -46.3%
bs=10 sw=10 sl=64 p50 24,243 us 25,090 us 13,009 us -3.4% +86.4%
bs=10 sw=10 sl=64 p95 33,673 us 31,218 us 15,463 us +7.9% +117.8%
bs=10 sw=10 sl=64 p99 33,673 us 31,218 us 18,561 us +7.9% +81.4%
bs=100 sw=10 sl=64 throughput 793 tuples/sec 816 tuples/sec 963.83 tuples/sec -2.8% -17.7%
bs=100 sw=10 sl=64 MB/s 0.484 MB/s 0.498 MB/s 0.588 MB/s -2.8% -17.7%
bs=100 sw=10 sl=64 p50 125,962 us 121,969 us 103,320 us +3.3% +21.9%
bs=100 sw=10 sl=64 p95 137,936 us 153,116 us 110,058 us -9.9% +25.3%
bs=100 sw=10 sl=64 p99 137,936 us 153,116 us 118,543 us -9.9% +16.4%
bs=1000 sw=10 sl=64 throughput 932 tuples/sec 918 tuples/sec 989.07 tuples/sec +1.5% -5.8%
bs=1000 sw=10 sl=64 MB/s 0.569 MB/s 0.56 MB/s 0.604 MB/s +1.6% -5.7%
bs=1000 sw=10 sl=64 p50 1,075,477 us 1,091,442 us 1,015,599 us -1.5% +5.9%
bs=1000 sw=10 sl=64 p95 1,134,053 us 1,118,482 us 1,055,944 us +1.4% +7.4%
bs=1000 sw=10 sl=64 p99 1,134,053 us 1,118,482 us 1,086,834 us +1.4% +4.3%
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,492.69,200,128000,406,0.248,24242.73,33672.58,33672.58
1,100,10,64,20,2522.73,2000,1280000,793,0.484,125962.24,137935.69,137935.69
2,1000,10,64,20,21457.71,20000,12800000,932,0.569,1075476.88,1134053.12,1134053.12

@aglinxinyuan aglinxinyuan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks, left comments inline

The idea is not bad, many services (e.g., google doc) has this force refresh alert.

The only big downside is what if a user is in the middle of something where he/she can lose unsaved progress. For workflow edits/execution etc probably be fine, because we do fine grained millisecond level auto save. But some cases where we have not taken care of, could have issues. For instance, when I am uploading very large files, can this interrupt?

Or do we have the assumption that frontend deployment happens only with backend service restart? then all operations are disconnected, anyway.

Comment thread frontend/src/app/app.component.spec.ts Outdated
Comment thread frontend/src/app/app.component.ts Outdated
Comment on lines +46 to +47
private config: GuiConfigService,
private deploymentVersion: DeploymentVersionService

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

configService and deploymentVersionService

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Renamed to configService and deploymentVersionService.

Comment thread frontend/src/app/app.component.ts Outdated
Comment thread frontend/build-version.js
Comment on lines +41 to +47
function main() {
const { version } = require("./package.json");
const { buildNumber, prodTs, manifestJson } = renderVersionArtifacts(version);
writeFileSync(resolve(__dirname, "src", "environments", "version.prod.ts"), prodTs);
writeFileSync(resolve(__dirname, "src", "assets", "version.json"), manifestJson);
console.log(`build-version: ${buildNumber}`);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is it the only way to write a file? how about use an env variable?

either way we have to take care of the file life cycle: who is going to delete this file/env variable?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

An env var won't work: the browser fetches version.json at runtime to read the deployed version, and it can't read a server-side env var. Both generated files are gitignored and rewritten in place every build, so there's nothing to clean up.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

they are replaced but they are never removed. it is not that clean of a solution.

can this be stored in the memory instead? It can be written once at service deployment. the frontend/browser go ahead fetches it whenever connects. And we don't have to leave file behind on disk, and we won't need to deal with its life cycle (removal, git ignore, etc).

Ma77Ball added 3 commits June 24, 2026 01:12
  refactor(frontend): address review feedback on
  deployment version check

  - Test the real
  NotificationService/DeploymentVersionService with
  vi.spyOn
    instead of hand-rolled fakes, stubbing only
  ng-zorro's lower-level services
  - Make the reload notification actionable: blank()
  returns the NzNotificationRef
    and promptReload() reloads the page on click
  (guarded with take(1))
  - Rename start() -> startPollingForUpdates() for
  clearer intent
  - Rename AppComponent constructor params to
  configService/deploymentVersionService
@Ma77Ball Ma77Ball force-pushed the feat/deployment-version-check branch from 49b77f0 to 7502d56 Compare June 26, 2026 19:04
@Ma77Ball Ma77Ball requested a review from Yicong-Huang June 26, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

common feature frontend Changes related to the frontend GUI platform Non-amber Scala service paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detect a new frontend deployment at runtime and prompt the user to reload

5 participants