Skip to content

improvement(files): cache stream binding meta, tighten file cache-control, prune dead persist path - #6149

Merged
waleedlatif1 merged 2 commits into
stagingfrom
files-perf-improvements
Aug 1, 2026
Merged

improvement(files): cache stream binding meta, tighten file cache-control, prune dead persist path#6149
waleedlatif1 merged 2 commits into
stagingfrom
files-perf-improvements

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Cache the agent-stream ProseMirror↔Yjs binding metadata per session and reuse it across streamed frames instead of rebuilding it (O(doc)) each frame — mirrors how y-tiptap's own binding maintains the mapping in place. Safe because the shadow doc only ever sees the agent's own reconciles.
  • Default createFileResponse to private, no-cache so auth-gated bytes are never stored in a shared cache; genuinely-public serve routes opt into public caching explicitly.
  • Serve content-addressed (key=) embedded images with an immutable private cache to avoid re-downloading them on every doc re-open; fileId= embeds and public shares keep revalidating (the key can change / a share can be revoked).
  • Drop the dead conflict.version field from the collab-doc persist result and remove the wasted getWorkspaceFile re-read on the conflict path (the relay treats missing and conflict identically and never read version).
  • Decorate-sort the files/folders lists (compute each sort key once) and index the move-menu subtree build (O(N) vs O(N²)); ordering is preserved exactly.

Type of Change

  • Improvement (performance + correctness + cleanup)

Testing

  • Benchmarked the meta cache: ~1.88ms → ~1.66ms per streamed frame on a 300-paragraph doc (rebuild removed; scales with doc size).
  • Added guard tests: default-private cache, explicit-public honored, key=→immutable vs fileId=→revalidate inline headers, and cross-frame meta reuse with no paragraph duplication.
  • lint, api-validation, typecheck (sim + realtime), and all affected suites (62 sim + 60 realtime) pass.
  • Adversarially audited every changed LOC across correctness, performance/over-engineering, and code-quality — all clean (correctness verified against the y-tiptap library source).

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…trol, prune dead persist path

- Cache the agent-stream ProseMirror↔Yjs binding metadata per session and reuse it
  across streamed frames instead of rebuilding it (O(doc)) every frame; matches how
  y-tiptap's own binding maintains the mapping in place. Safe because the shadow doc
  only ever sees the agent's own reconciles.
- Default createFileResponse to a private, no-cache policy so auth-gated bytes are never
  stored in a shared cache; genuinely-public serve routes opt into public caching
  explicitly.
- Serve content-addressed (key=) embedded images with an immutable private cache to
  avoid re-downloading them on every doc re-open; fileId= embeds and public shares keep
  revalidating (the underlying key can change / a share can be revoked).
- Drop the dead conflict.version field from the collab-doc persist result and remove the
  wasted getWorkspaceFile re-read on the conflict path (the relay treats missing and
  conflict identically and never read version).
- Decorate-sort the files/folders lists (compute each sort key once) and index the
  move-menu subtree build (O(N) vs O(N^2)); ordering is preserved exactly.
@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Aug 1, 2026 2:58am

Request Review

@cursor

cursor Bot commented Aug 1, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Cache-Control defaults and persist conflict semantics affect cross-user caching and collaborative durability; changes are intentional and tested, but regressions would show up as stale authorized images or incorrect relay behavior after version conflicts.

Overview
Hardens file serving cache policy so post-auth responses default to private, no-cache in createFileResponse (replacing a long-lived public default that could leak verified bytes through shared caches). Truly public assets (avatars, OG images, workspace logos) now opt in via an explicit PUBLIC_ASSET_CACHE_CONTROL on the serve route; inline embedded images keep always revalidate semantics with clearer documentation.

Speeds agent markdown streaming by caching ProseMirror↔Yjs meta on AgentStreamSession and reusing it across frames instead of calling initProseMirrorDoc every frame—updateYFragment maintains the mapping in place, with a new test guarding minimal deltas and no duplication.

Aligns collab-doc persist on conflict: the conflict result drops the unused version field across the API contract, realtime client types, and persistFileDoc—on If-Match failure the relay stops after one attempt and does not re-read the file or adopt a new version (avoids clobbering out-of-band writes).

UI list performance in files.tsx: decorate-sort for folder/file lists (keys computed once) and an indexed children-by-parent map for the move-menu tree (O(N) vs O(N²)).

Reviewed by Cursor Bugbot for commit 04e8424. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves file-serving safety and performance while simplifying collaborative persistence.

  • Makes authenticated file responses private by default and requires inline images to revalidate on every request.
  • Explicitly preserves public caching for public asset routes.
  • Reuses ProseMirror–Yjs binding metadata across streamed frames.
  • Removes the unused conflict version lookup and field from collaborative persistence.
  • Precomputes file and folder sort keys and indexes move-menu children to reduce repeated work.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the inline-image cache bypass is fixed, and the removed conflict metadata was not consumed by the relay.

Important Files Changed

Filename Overview
apps/sim/app/api/files/serve-inline-image.ts Applies a single private, revalidating policy to authenticated inline images, fully addressing the prior stale-cache bypass.
apps/sim/app/api/files/utils.ts Changes the generic file-response default from public caching to private revalidation while retaining explicit overrides.
apps/sim/app/api/files/serve/[...path]/route.ts Explicitly opts genuinely public assets into shared caching after the generic response default became private.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/collaboration/apply-streamed-markdown.ts Caches binding metadata within each isolated agent stream session and reuses it across frames.
apps/sim/app/workspace/[workspaceId]/files/files.tsx Precomputes sort keys and indexes folder children without changing established ordering behavior.
apps/sim/lib/collab-doc/persist.ts Removes an unconsumed conflict-version reread while preserving the relay’s existing conflict behavior.
apps/sim/lib/api/contracts/file-doc.ts Aligns the persistence response contract with the status-only conflict result consumed by realtime.
apps/realtime/src/handlers/file-doc-app.ts Aligns the realtime client type and documentation with the status-only conflict response.

Reviews (3): Last reviewed commit: "fix(files): serve inline images with no-..." | Re-trigger Greptile

Comment thread apps/sim/app/api/workspaces/[id]/files/inline/route.ts Outdated
Comment thread apps/sim/lib/collab-doc/persist.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit dde9ff5. Configure here.

…on is enforced per request

Embedded images are authenticated content whose backing file can be deleted or have its
access revoked at any time. Both key= and fileId= embeds serve
private, no-cache, must-revalidate, so every request re-runs the server-side
deletion/authorization check instead of serving a possibly-stale image from cache.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 04e8424. Configure here.

@waleedlatif1
waleedlatif1 merged commit 06506bb into staging Aug 1, 2026
50 checks passed
@waleedlatif1
waleedlatif1 deleted the files-perf-improvements branch August 1, 2026 03:09
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