Skip to content

Expose invalidate_forest_cache through fula-flutter bindings (0.6.8): session-pinned forests serve stale cross-device listings #36

@ehsan6sha

Description

@ehsan6sha

Problem

The encrypted client caches each bucket forest for the CLIENT LIFETIME: load_forest is a no-op once cached (verified: 0ms on second call via perf spans) and list_from_forest / get_object_flat read that memory. Any long-lived session therefore never sees another device''s uploads - listings, manifest reads AND downloads all resolve against the session-stale forest.

Real repro (FxFiles web, 2026-06-12): upload from desktop web -> a long-lived mobile web tab kept showing the old 2-file listing indefinitely (incognito on the same phone showed 3). The app''s SWR cache then re-stamped the stale listing as fresh because its live revalidation was actually a memory read. The same lifetime-pinning affects the NATIVE apps on long sessions.

The fix is already written - it just isn''t exposed

EncryptedClient::invalidate_forest_cache(&self, bucket) exists at crates/fula-client/src/encryption.rs:9015 (dirty-safe: keeps unsaved entries) plus invalidate_all_forest_caches at :9029. Neither is reachable from Dart: crates/fula-flutter/src/api/forest.rs exposes load/save/flush only.

Ask (0.6.8)

  1. Add to crates/fula-flutter/src/api/forest.rs:
    • invalidate_forest_cache(client, bucket) -> guard read -> call through
    • optionally invalidate_all_forest_caches(client)
  2. Release via the existing hash-consistent pipeline (FRB_CODEGEN_VERSION pinned 2.11.1, build-flutter-wasm job producing flutter-wasm-pkg.zip - same flow as v0.6.7).
  3. Consider exposing the same in crates/fula-js for npm parity.

Consumer side (FxFiles, ready and waiting)

FulaApiService.invalidateForestCache(bucket) (FxFiles commit cfaa185) already drops the Dart-side memo and is called on every SWR revalidation/force path - it just needs the Rust call added once 0.6.8 lands. FxFiles currently ships an interim workaround (full client rebuild from stored credentials on Refresh/tab-resume/reconnect) that 0.6.8 makes cheap and per-bucket. Native apps can adopt the same call for their cloud-listing refreshes.

Acceptance

  • After another client uploads to a bucket, invalidate_forest_cache(bucket) + list_from_forest on an existing client returns the new file (no client rebuild).
  • A dirty (unsaved local changes) forest is NOT evicted - existing doc contract.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions