Skip to content

Android: EditorService's cache policy never refreshes plugin and theme assets #753

Description

@jkmassel

Description

EditorService's cache policy is documented to cover plugin and theme assets, but on Android it never does. Once any asset bundle is on disk, prepare() returns the newest one without checking the site's editor-assets manifest, whatever the policy:

private suspend fun prepareAssetBundle(): EditorAssetBundle {
    val latestAssetBundle = assetLibrary.readAssetBundles().firstOrNull()
    if (latestAssetBundle != null) {
        incrementProgress(DependencyWeights.ASSET_BUNDLE)
        return latestAssetBundle
    }
    // …
}

(EditorService.kt#L272-L282)

EditorCachePolicy.MaxAge and EditorCachePolicy.Ignore refresh API responses and never assets. The only way to pick up a plugin or theme change is purge(), which deletes everything first and forces a cold load for the next editor.

For assets, the policy is consulted in one place, EditorAssetsLibrary.fetchManifest(). The service only calls it when there is no bundle on disk, and there the policy only decides whether to parse the manifest again.

iOS had the same gap. #742 closes it there, and docs/code/preloading.md describes the behavior Android should match.

Expected behavior

The policy decides when to check the site's manifest again:

Policy Today Expected
Always (default) Manifest checked only when no bundle is on disk Unchanged
MaxAge Same as Always Manifest checked once the last check is older than the age
Ignore Same as Always Manifest checked on every prepare()

An unchanged manifest keeps the bundle already on disk rather than downloading every asset again — asset URLs carry their version (?ver=), so the same manifest means the same assets. A changed manifest builds a new bundle beside the old one.

A host can then refresh a site's editor data with EditorService.create(…, cachePolicy = EditorCachePolicy.Ignore).prepare(), without purge().

Related gaps found on iOS

#742 also fixes three problems on iOS that Android's code shares. They're worth doing in the same change, since a refresh makes each of them more visible:

  • Download progress passes its total. buildBundle reports a running total (EditorAssetsLibrary.kt#L208), and incrementProgress adds that fraction of the bundle's weight in full on every report (EditorService.kt#L252). With 4 assets the bundle contributes 12 + 25 + 37 + 50 = 124 against a weight of 50. On iOS the same arithmetic reached 175 of 100.
  • Automatic cleanup shares one daily turn between every site. The key is once-every-cleanup for all of them (EditorService.kt#L208-L210), so whichever site is prepared first each day uses it. That hasn't mattered while a site only ever has one bundle; once a refresh builds a second, the others' old bundles linger.
  • cleanup() deletes every bundle but the newest, including one that an open editor or EditorDependencies the host prepared earlier still reads (EditorAssetsLibrary.kt#L284). iOS now keeps any bundle handed out since launch.

Design notes from the iOS change

  • "Latest" can't be the newest downloadDate: a site can go back to a manifest it had before, whose bundle was downloaded earlier than the one it replaced. iOS stamps a separate lastCheckedDate in the bundle's manifest and orders by that, leaving downloadDate alone.
  • The bundle has to be looked for again, under a lock shared with cleanup() and purge(), before it's marked as the latest. Otherwise a cleanup landing between the check and the write leaves a directory holding only manifest.json, and the editor opens without plugin or theme assets.
  • A manifest check should ask the site afresh rather than take a cached response or join a request already in flight.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Android[Type] BugAn existing feature does not function as intended

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions