Skip to content

feat(desktop-gpui): implement upload speed test and network health check (#73) - #3706

Open
cocvn157 wants to merge 3 commits into
CapSoftware:mainfrom
cocvn157:feat/issue-73-desktop-gpui-network-health
Open

cocvn157 wants to merge 3 commits into
CapSoftware:mainfrom
cocvn157:feat/issue-73-desktop-gpui-network-health

Conversation

@cocvn157

@cocvn157 cocvn157 commented Nov 4, 2026 •

Copy link
Copy Markdown

Adds upload speed testing and storage write health checks across apps/desktop-gpui and apps/web. POST /api/desktop/upload-health measures throughput against the active organization's recording storage target (S3 or Google Drive) using a temporary probe key under .cap-upload-health/ that is deleted immediately after the check.

On the desktop side, apps/desktop-gpui/src/network_health.rs runs background probes every 10 minutes (pausing while active recordings or uploads hold a TransferLease), exposes a manual test button in General Settings and a status indicator in the recording window, and falls back from Instant Mode to Studio Mode when upload health is degraded or unverified.

Fixes #73
/claim #73

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the remaining probe-cleanup issue is non-blocking.

Findings

  1. P2 Timed-out probes leave objects behind ▶
Fix with agent prompt
### Issue 1
apps/web/lib/upload-health.ts:55-59
`checkUploadStorage` can leave probe objects behind when a storage write takes longer than 10 seconds. The S3 write runs through a promise without an abort signal, so the timeout stops waiting but does not stop the write. Cleanup can delete the key before the write finishes, leaving the completed object behind.

This is non-blocking, but slow or retrying storage connections can accumulate small probe objects. Wait for the write to settle before deleting, or arrange a later cleanup for timed-out writes.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Adds upload checks to the GPUI desktop app and a matching authenticated API.

  • Desktop checks measure upload speed and write access for recording storage.
  • Desktop GPUI shows upload health and adjusts Instant recordings.

The refresh interval and background-upload fixes address the first two previous findings. No new actionable issues were found.

Reviews (3) · Last reviewed commit: "fix(desktop-gpui): refresh probes before..." · Reviewed by Greptile

@vercel

vercel Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
cap-status Skipped Skipped Nov 6, 2026 1:45pm UTC

@vercel
vercel Bot temporarily deployed to Preview – cap-status November 4, 2026 05:09 Inactive
Comment thread apps/desktop-gpui/src/network_health.rs Outdated

use crate::{auth, session::RecordingSession, store};

const AUTOMATIC_PROBE_INTERVAL: Duration = Duration::from_secs(60 * 60);

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.

P1 Resolution limits expire between checks

Automatic checks run once an hour, but Measurement expires after 15 minutes. After a slow connection receives a resolution limit, recordings started between minutes 15 and 60 use the higher saved resolution, even if the connection has not changed.

Refresh before MEASUREMENT_TTL expires, or request a fresh check before starting Instant recording with an expired result.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop-gpui/src/network_health.rs
Line: 15

Comment:
**Resolution limits expire between checks**

Automatic checks run once an hour, but `Measurement` expires after 15 minutes. After a slow connection receives a resolution limit, recordings started between minutes 15 and 60 use the higher saved resolution, even if the connection has not changed.

Refresh before `MEASUREMENT_TTL` expires, or request a fresh check before starting Instant recording with an expired result.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment thread apps/desktop-gpui/src/network_health.rs Outdated
Comment on lines +254 to +258
if state.running.is_some()
|| RecordingSession::recording_in_flight(cx)
|| state
.attempted_at
.is_some_and(|at| at.elapsed().is_ok_and(|age| age < interval))

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.

P2 Checks compete with background uploads

request() pauses checks during recording, but not during background uploads. The upload queue can resume saved recordings while RecordingSession is idle, so a check can send two 2 MiB samples alongside a real upload. This slows the upload and can produce a lower speed reading that unnecessarily reduces the next recording's resolution.

Include active queue transfers in the shared admission gate, including transfers that start after a check begins.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop-gpui/src/network_health.rs
Line: 254-258

Comment:
**Checks compete with background uploads**

`request()` pauses checks during recording, but not during background uploads. The upload queue can resume saved recordings while `RecordingSession` is idle, so a check can send two 2 MiB samples alongside a real upload. This slows the upload and can produce a lower speed reading that unnecessarily reduces the next recording's resolution.

Include active queue transfers in the shared admission gate, including transfers that start after a check begins.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@vercel
vercel Bot temporarily deployed to Preview – cap-status November 4, 2026 05:26 Inactive
@richiemcilroy

Copy link
Copy Markdown
Member

Thanks! Can you rebase on main to clear the conflicts and get Greptile to 5/5 on the latest commit? Then we'll take a look.

@cocvn157
cocvn157 force-pushed the feat/issue-73-desktop-gpui-network-health branch from 5e0e18d to 3ac1bca Compare November 5, 2026 02:50
@vercel
vercel Bot temporarily deployed to Preview – cap-status November 5, 2026 02:50 Inactive
@cocvn157

cocvn157 commented Nov 5, 2026 •

Copy link
Copy Markdown
Author

@richiemcilroy Rebased on latest main and addressed the Greptile feedback (shortened the background probe refresh interval to 10m so measurements don't expire before the 15m TTL, and wired active uploads into TransferLease so background checks don't compete with in-flight transfers). Greptile is back at 5/5 on the latest commit whenever you get a chance to take a look!

Comment on lines +55 to +59
return put(key, bytes).pipe(
Effect.timeout("10 seconds"),
Effect.ensuring(
remove(key).pipe(
Effect.timeout("3 seconds"),

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.

P2 Timed-out probes leave objects behind

checkUploadStorage can leave probe objects behind when a storage write takes longer than 10 seconds. The S3 write runs through a promise without an abort signal, so the timeout stops waiting but does not stop the write. Cleanup can delete the key before the write finishes, leaving the completed object behind.

This is non-blocking, but slow or retrying storage connections can accumulate small probe objects. Wait for the write to settle before deleting, or arrange a later cleanup for timed-out writes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/lib/upload-health.ts
Line: 55-59

Comment:
**Timed-out probes leave objects behind**

`checkUploadStorage` can leave probe objects behind when a storage write takes longer than 10 seconds. The S3 write runs through a promise without an abort signal, so the timeout stops waiting but does not stop the write. Cleanup can delete the key before the write finishes, leaving the completed object behind.

This is non-blocking, but slow or retrying storage connections can accumulate small probe objects. Wait for the write to settle before deleting, or arrange a later cleanup for timed-out writes.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch, threaded Effect's AbortSignal into S3 putObject and Google Drive upload requests in 674e41f so timed-out probe writes abort before cleanup runs.

@cocvn157
cocvn157 force-pushed the feat/issue-73-desktop-gpui-network-health branch from 3ac1bca to 81e216b Compare November 6, 2026 02:07
@vercel
vercel Bot temporarily deployed to Preview – cap-status November 6, 2026 02:07 Inactive
@vercel
vercel Bot temporarily deployed to Preview – cap-status November 6, 2026 13:45 Inactive
@cocvn157

cocvn157 commented Nov 9, 2026 •

Copy link
Copy Markdown
Author

Hi @richiemcilroy — just a quick heads-up that the follow-up Greptile point on apps/web/lib/upload-health.ts (threading AbortSignal into the S3/Drive probe uploads so timed-out probes abort cleanly before cleanup) was resolved in 674e41f, and Greptile is at 5/5 on the latest commit with no merge conflicts. Ready for another look whenever you have a moment!

This branch was previously deployed

1 inactive deployment
Preview – cap-status — 674e41fb Deployed Nov 6, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement speed test and health check for Cap desktop app

2 participants