No task waits on a Codex review; the redesign tasks are confirmed on the product owner's Z Fold7; TASK-016's leftovers are on hold; no biometric reauthentication. Agent: main (opus) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
109 lines
6.0 KiB
Markdown
109 lines
6.0 KiB
Markdown
# TASK-046: Commit history load performance and loading feedback
|
|
|
|
Status: implemented; all required checks pass; live-confirmed on the human product owner's device
|
|
Owner: Claude
|
|
Reviewer: Codex
|
|
|
|
## Outcome
|
|
|
|
Live-testing TASK-045's redesign surfaced a real, pre-existing bug: opening the 커밋 (commit history)
|
|
tab on a real, large company repository (`RobotAutomationDevelopment-Dept/LGES-OC5-PtoP-Welder`)
|
|
consistently failed with "서버에 연결할 수 없습니다" (offline error), even though the device had a
|
|
normal network connection throughout. Root-caused, fixed, and confirmed live with the product owner.
|
|
|
|
## Scope
|
|
|
|
- Included: `GiteaRepositoryBrowserApi.listCommits` now requests `stat=false`; `HttpTransport`'s
|
|
shared OkHttp client's `readTimeout` raised 30s -> 60s as a safety margin; a new
|
|
`EstimatedProgressIndicator` (percentage progress bar) replaces the plain spinner on History's
|
|
three loading states.
|
|
- Excluded: no change to any other API call's stat/file-list behavior (only the commit-list
|
|
endpoint was touched); no change to commit detail, which legitimately needs per-file data and
|
|
correctly keeps returning it.
|
|
|
|
## Root cause
|
|
|
|
Gitea's `GET /repos/{owner}/{repo}/commits` endpoint computes and returns full per-commit file-change
|
|
lists and add/remove line stats by default, regardless of what the client asked for. This particular
|
|
repository's history contains one commit (a vendored `packages/` folder checked into git) touching
|
|
~5.8 million lines. Computing that commit's stats made the *entire request* -- even a 5-item page --
|
|
take 31+ seconds server-side, tripping the client's then-30s read timeout. Live-measured directly
|
|
against the real endpoint:
|
|
|
|
```text
|
|
default (stat computed): 31.3s, 678653 bytes
|
|
stat=false: 0.4s, 678567 bytes
|
|
```
|
|
|
|
Note the response size is nearly identical either way -- the cost is server-side compute time, not
|
|
payload size. `GiteaRepositoryBrowserApi.mapCommit` only ever reads `sha`/`commit.message`/
|
|
`commit.author.{name,date}` from this response; it never reads `files` or `stats`. `stat=false` is
|
|
therefore a pure win: Gitea skips work the app already threw away, with no loss of data the app used.
|
|
|
|
## Design notes
|
|
|
|
- **`stat=false` is the real fix; the timeout bump and progress bar are defense in depth**, not the
|
|
primary fix -- kept anyway since OkHttp's previous 30s ceiling was already documented (see
|
|
`HttpTransport.kt`'s existing comment) as too tight for other genuinely-slow cases against this
|
|
same home-NAS-hosted Gitea instance (e.g. very large directory listings), and a percentage
|
|
indicator is a real UX improvement for any request that legitimately takes a while.
|
|
- **The progress bar is a time-based estimate, not a byte-accurate percentage.** Confirmed via a live
|
|
header check that Gitea serves this endpoint `Transfer-Encoding: chunked` with no `Content-Length`,
|
|
so there is no real total-bytes figure to compute a true percentage from. `EstimatedProgressIndicator`
|
|
ramps linearly toward a 94% cap over an assumed ~20s typical duration and holds there until the real
|
|
response arrives (replacing the whole composable with actual content/error) -- it never visually
|
|
claims 100% before the data is actually in. This trade-off (an honest estimate, not a precise
|
|
measurement) was not explicitly re-confirmed with the product owner after implementing, since the
|
|
underlying request became near-instant once `stat=false` was added, making the estimate's accuracy
|
|
largely moot in practice.
|
|
- **Applied to all three of History's loading states** (commit list, commit detail, patch), not just
|
|
the one that was reported, since all three hit the same class of Gitea host and the fix is a
|
|
same-shape, low-risk composable swap.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [x] `listCommits` requests `stat=false`.
|
|
- [x] Live-measured against the real failing repository: request completes in under a second instead
|
|
of 30+.
|
|
- [x] Loading states show an estimated percentage progress bar instead of a bare spinner.
|
|
- [x] No change to what `CommitSummary` exposes or how it's built.
|
|
- [x] Build, unit tests (including a new query-parameter assertion), and lint pass.
|
|
- [x] Live-confirmed on the human product owner's device, against the exact repository that
|
|
originally failed.
|
|
|
|
## Required checks
|
|
|
|
```text
|
|
./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug
|
|
```
|
|
|
|
## Evidence
|
|
|
|
- `data/repositories/GiteaRepositoryBrowserApi.kt`: `listCommits` adds `.addQueryParameter("stat", "false")`.
|
|
- `core/network/HttpTransport.kt`: `readTimeout` 30s -> 60s, comment extended with this task's
|
|
measured numbers.
|
|
- `feature/history/HistoryScreen.kt`: new `EstimatedProgressIndicator` + `history_loading_progress`
|
|
string, replacing `CircularProgressIndicator()` at all three loading call sites (commit list,
|
|
commit detail, patch).
|
|
- `GiteaRepositoryBrowserApiTest.kt`: existing `listCommits` test extended to assert
|
|
`url.queryParameter("stat") == "false"`.
|
|
- Direct `curl` measurement against the live server (see Root cause above): 31.3s -> 0.4s, near-identical
|
|
response size either way.
|
|
- `./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug`:
|
|
BUILD SUCCESSFUL, all unit tests passing, 0 lint errors.
|
|
- Live device: installed over wireless `adb`. Human product owner navigated to the previously-failing
|
|
repository's commit tab themselves and confirmed it now works well ("내가 확인했어").
|
|
|
|
## Known limitations
|
|
|
|
- The progress percentage is a time-based estimate (see Design notes), not derived from real bytes
|
|
transferred -- inherent to Gitea serving this endpoint as chunked with no `Content-Length`.
|
|
- Only `listCommits` (the list endpoint) was changed. If a future repository has a similarly huge
|
|
commit and a user opens that commit's *detail* view, the detail fetch still legitimately needs and
|
|
requests full file/stat data, and could be slow for the same underlying reason -- not fixable the
|
|
same way, since that view's entire purpose is showing the file changes.
|
|
|
|
## Review findings
|
|
|
|
None yet -- no Codex review pending (Codex retired, 2026-09-29).
|