Skip to content

fix(runtime): move large session blobs out of entry rows#242

Open
mhart wants to merge 4 commits into
withastro:mainfrom
mhart:mhart/external-session-data
Open

fix(runtime): move large session blobs out of entry rows#242
mhart wants to merge 4 commits into
withastro:mainfrom
mhart:mhart/external-session-data

Conversation

@mhart

@mhart mhart commented Jun 11, 2026

Copy link
Copy Markdown

Builds on the session-entry storage added in main by moving large inline session payloads out of each entry JSON row.

Summary

  • Stores image/blob/document/file payloads in flue_session_blobs instead of inline in flue_session_entries.data.
  • Chunks blob data in SQL by default, so built-in Node SQLite and Cloudflare Durable Object SQLite avoid oversized cells without extra configuration.
  • Adds SessionAttachmentStore for optional external blob storage.
  • Wires Cloudflare to use an R2 binding named FLUE_SESSION_ATTACHMENTS when present.
  • Exposes the same attachment-store option from the Node SQLite adapter for filesystem, S3-compatible, or application-provided stores.
  • Keeps SQL as the authoritative manifest for blob references and cleanup state.
  • Adds retry tracking for failed external object deletes.
  • Adds schema migration handling for intermediate flue_session_blobs schemas.

Behavior

Without external attachment storage, blobs remain in SQL chunk rows.

On Cloudflare, defining an R2 binding named FLUE_SESSION_ATTACHMENTS stores large blobs externally in R2. Without that binding, Cloudflare falls back to SQL chunk rows.

On Node SQLite, callers can pass a custom attachmentStore; otherwise Node keeps using SQL chunk rows.

Fixes #240

@mhart mhart changed the title Mhart/external session data fix(runtime): store SQL sessions with chunked blobs and support external storage Jun 11, 2026
@mhart mhart force-pushed the mhart/external-session-data branch 2 times, most recently from 7d41b3b to aa2c7b1 Compare June 11, 2026 09:19
@FredKSchott

Copy link
Copy Markdown
Member

no need to rebase / worry about merge conflicts FYI, if we actually decide to ship this well probably do a clean re-implementation. Also you need to handle for Node, not just Cloudflare. Can you look into how hard that would be?

@mhart

mhart commented Jun 11, 2026

Copy link
Copy Markdown
Author

no need to rebase

Yeah this is my habit of amending / rewriting commits coming through – not rebasing to deal with merge conflicts in this case. Still a stickler for a clean commit history! The GH UI has changed over the years to make this look messier than it is though, I agree.

Playing with some more generic Node-friendly options as we speak

mhart added 2 commits June 11, 2026 20:54
Build on the SQL session-entry storage added upstream by moving inline image/blob/document/file payloads out of each entry JSON row.

Large payloads are stored in flue_session_blobs and rehydrated on load, preserving session data while avoiding oversized SQLite cells.

Fixes withastro#240
Add a generic SessionAttachmentStore option for SQL-backed session blobs so large payloads can be stored outside the database when configured.

Cloudflare wires this to an R2 bucket binding, while Node SQLite exposes the same option for custom filesystem, S3-compatible, or application-provided attachment stores. The default remains SQL chunk storage.
@mhart mhart force-pushed the mhart/external-session-data branch from aa2c7b1 to de4617e Compare June 11, 2026 10:58
@mhart

mhart commented Jun 11, 2026

Copy link
Copy Markdown
Author

Ok, so because this PR introduces chunking of blobs, there's no need for Node users to do anything specific (or Cloudflare users for that matter) – the chunking should handle large attachments anyway.

However, you also have the option to use a custom attachmentStore. On Cloudflare that can be R2. On Node I'm going to explore using the filesystem. There could also be a generic S3-compatible API store, it would just introduce an extra dependency, so not sure about that one.

mhart added 2 commits June 11, 2026 21:18
Add fileSessionAttachmentStore() for Node SQLite persistence so large session
blob attachments can be stored on the local filesystem via the existing
SessionAttachmentStore option.

The helper writes files under a configured root, rejects path traversal, uses a
temporary file plus rename for writes, and keeps SQL as the authoritative
attachment manifest.
- Made session blob table rebuilds run inside the Node/Cloudflare transaction wrappers.
- Queued cleanup for attempted external uploads when a later upload fails.
- Restricted blob ref hydration to actual message content `data`/`blob` fields, so metadata with ref-shaped JSON is preserved.
- Tightened `PreparedSessionBlob` typing and removed the double entry-serialization pass.
- Added regression tests for upload cleanup, migration rollback, and blob-ref-shaped metadata.
@mhart mhart changed the title fix(runtime): store SQL sessions with chunked blobs and support external storage fix(runtime): move large session blobs out of entry rows Jun 11, 2026
@FredKSchott

Copy link
Copy Markdown
Member

Fixed on main by 64ae6e6 with chunked SQLite image persistence plus direct HTTP and SDK image support, so I'm closing this as superseded. Thanks for exploring this space and for the useful reference implementation. Adding a bucket-storage primitive is out of scope for this iteration given the added configuration and lifecycle complexity, but it is definitely worth keeping in mind as attachment-size requirements grow.

@FredKSchott FredKSchott reopened this Jun 13, 2026
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.

SQLITE_TOOBIG when sessions are larger than 2MB

2 participants