Skip to content

fix(app): fetch the content manifest once per burst, not once per screen - #17

Open
IgnacioLD wants to merge 1 commit into
mainfrom
fix/manifest-refetch
Open

IgnacioLD wants to merge 1 commit into
mainfrom
fix/manifest-refetch

Conversation

@IgnacioLD

Copy link
Copy Markdown
Owner

Problem

Every ViewModel built its own GlossoApi (AppServices.newApi), each with its own manifest lock, lastManifest and HTTP client. On start several screens ask for /v1/content/manifest (~900 KB) at the same moment, so with an empty HTTP cache (fresh install, content version change, server switch) the full body was downloaded 3 times, and every launch sent 4 requests.

Fix

  • ViewModels use the process-wide appApi; AppServices.newApi is removed.
  • GlossoApi.manifest() is single-flight: a call that waited while another fetch ran takes that result, only when it was for the same server and language (a switch from feat(app): let the learner point the app at a self-hosted server #15 can land mid-fetch). Later calls still revalidate with the ETag (cheap 304), so newly published content still shows up.
  • ensureAssetVersion() goes through the same path.

Measured against a local server (counted in the server log)

Session: fresh install, cold launch, skip onboarding, Lessons, Library, Today, open a lesson, practice, background, foreground, kill + relaunch.

before after
iOS (iPhone Air sim) 3x 200 + 8x 304 1x 200 + 5x 304
Android (emulator) 3x 200 + 8x 304 1x 200 + 5x 304
relaunch alone 4 requests 2 requests

The earlier report of ~54 full downloads was not reproducible without the proxy: with a warm cache the app sends 304 revalidations, so the proxy most likely broke the conditional requests.

Tests

  • New GlossoApiManifestTest: 4 concurrent calls share 1 request (it fails before with 4), and a later call still revalidates.
  • :shared:testAndroidHostTest, :androidApp:testPlaystoreDebugUnitTest, :androidApp:testFdroidDebugUnitTest, :androidApp:lintPlaystoreDebug pass.

https://claude.ai/code/session_01FcVpZoyr8VdRLp1QecX1Ng

Every ViewModel built its own GlossoApi, so each had its own manifest lock
and state. On start the Today, lessons, stories, exercises and practice
screens all asked for the ~900 KB manifest at once; with an empty HTTP cache
(fresh install, content version change, server switch) that downloaded it
three times, and every launch sent four requests.

ViewModels now use the process-wide appApi, and manifest() is single-flight:
a call that waited while another fetch ran takes its result (only for the
same server and language).

Claude-Session: https://claude.ai/code/session_01FcVpZoyr8VdRLp1QecX1Ng
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant