feat(export): bundle session caches into html-wasm --execute output#9897
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
June 24, 2026 22:57
9d26af1 to
6d6f2df
Compare
dmadisetti
force-pushed
the
dm/lazy-store-merge
branch
from
June 24, 2026 23:20
6cb26c5 to
45fbfde
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
June 24, 2026 23:21
b259019 to
d5cbda8
Compare
Contributor
|
Is this ready for review? Anything blocking moving it out of draft? |
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
June 29, 2026 17:58
d5cbda8 to
1a311e2
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
June 30, 2026 18:27
1a311e2 to
e8cdc61
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
June 30, 2026 19:25
e8cdc61 to
e79334e
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 1, 2026 21:16
e79334e to
dfd4acf
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 2, 2026 22:46
cd9695e to
1716f32
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 2, 2026 23:04
96dcc10 to
f67a52f
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 6, 2026 17:30
f67a52f to
89c55f1
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 6, 2026 17:42
89c55f1 to
1ad86c1
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 8, 2026 19:43
de03fc5 to
de482e1
Compare
dmadisetti
force-pushed
the
dm/cache-robustness
branch
from
July 8, 2026 20:27
32b44cb to
72f09a2
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 8, 2026 20:31
de482e1 to
9a0e277
Compare
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 8, 2026 23:26
9a0e277 to
862ed09
Compare
dmadisetti
marked this pull request as ready for review
July 8, 2026 23:44
Contributor
There was a problem hiding this comment.
Pull request overview
Adds support for bundling execution-time cell caches into marimo export html-wasm --execute output so exported WASM notebooks can reuse precomputed results (via public/cache/) instead of recomputing in-browser.
Changes:
- Introduces per-notebook cache export manifests (written on kernel teardown when caching is enabled) and a bundling step that copies manifest-listed blobs into
<out_dir>/public/cache/. - Extends the export execution path to optionally enable cache export behavior and to trigger bundling after the kernel completes.
- Adds focused unit tests for manifest naming/dumping and for cache bundling behavior (including traversal rejection).
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/_server/export/test_exporter.py | Adds a note clarifying where cache-export coverage lives. |
| tests/_save/loaders/test_cache_export.py | New unit tests for manifest naming, manifest dumping, and cache-export teardown gating. |
| tests/_cli/test_export_cache_bundle.py | New unit tests for bundling cache blobs into public/cache/ and safety behaviors. |
| marimo/_session/managers/kernel.py | Requests clean kernel shutdown and adds a bounded join to allow cache flush before kill. |
| marimo/_server/export/init.py | Implements manifest-based cache bundling and wires it into html-wasm --execute execution flow. |
| marimo/_save/stores/file.py | Adds export_manifest_name() helper for deriving the manifest filename. |
| marimo/_save/loaders/lazy.py | Adds manifest dumping and a merged export_keys() for bundling. |
| marimo/_save/loaders/init.py | Re-exports dump_cache_manifests. |
| marimo/_runtime/runtime.py | Wires CacheCallbacks to read cache_cells from config at teardown time. |
| marimo/_runtime/callbacks/cache.py | Adds cache_cells_enabled() and writes export manifests on teardown when enabled. |
| marimo/_runtime/callbacks/init.py | Exposes cache_cells_enabled. |
| marimo/_cli/export/commands.py | Passes cache_export_dir for html-wasm --execute runs and documents bundling behavior. |
Comment on lines
+394
to
+413
| try: | ||
| keys: list[str] = json.loads(manifest_file.read_text()) | ||
| except (OSError, ValueError) as e: | ||
| LOGGER.warning("Failed to read cache export manifest: %s", e) | ||
| return | ||
|
|
||
| cache_dst = out_dir / "public" / "cache" | ||
| copied = 0 | ||
| for key in keys: | ||
| # A stale/tampered manifest key could otherwise escape the cache dir. | ||
| rel = PurePosixPath(key) | ||
| if not isinstance(key, str) or rel.is_absolute() or ".." in rel.parts: | ||
| LOGGER.warning("Skipping unsafe cache manifest key: %r", key) | ||
| continue | ||
| src_file = cache_src / key | ||
| if src_file.exists(): | ||
| dst_file = cache_dst / key | ||
| dst_file.parent.mkdir(parents=True, exist_ok=True) | ||
| shutil.copy2(src_file, dst_file) | ||
| copied += 1 |
Comment on lines
+455
to
+472
| @@ -392,11 +456,20 @@ | |||
| resolved = config.get_config() | |||
| display_config = resolved["display"] | |||
|
|
|||
| if cache_export_dir is not None: | |||
| # NB. drop a prior run's manifest so we never bundle a stale key set. | |||
| _cache_export_manifest_path(path).unlink(missing_ok=True) | |||
|
|
|||
| session_view, did_error = await run_app_until_completion( | |||
| file_manager, | |||
| cli_args, | |||
| argv=argv, | |||
| cache_export=cache_export_dir is not None, | |||
| ) | |||
| if cache_export_dir is not None: | |||
| # NB. the run joined the kernel, which wrote the manifest on shutdown, | |||
| # so it's on disk to read now. | |||
| bundle_cache_export(path, cache_export_dir) | |||
Member
Author
There was a problem hiding this comment.
Good distinction. Making this more opt in
Comment on lines
+11
to
+22
| def export_manifest_name(notebook_filename: str | None) -> str: | ||
| """Filename of the export manifest for a notebook, derived from its path. | ||
|
|
||
| Per-notebook (not a shared name) so notebooks sharing a cache dir, or | ||
| concurrent exports, don't clobber each other. Kernel and exporter derive it | ||
| identically. A dotfile so it can't collide with a cache key. | ||
| """ | ||
| import re | ||
|
|
||
| stem = Path(notebook_filename).stem if notebook_filename else "notebook" | ||
| slug = re.sub(r"[^0-9A-Za-z._-]+", "-", stem).strip("-") or "notebook" | ||
| return f".{slug}-export.json" |
Bundle a session's per-cell and per-function caches into the output of marimo export html-wasm --execute, so a dependency-free browser (Pyodide) can skip recomputation. Stacked on the cache-robustness PR (#10109), which provides the graceful-degrade / hashing-parity restore machinery this relies on to consume the bundled caches without the original deps. This pull request was authored by a coding agent.
dmadisetti
force-pushed
the
dm/wasm-cache-export
branch
from
July 9, 2026 00:21
862ed09 to
1bb2d02
Compare
peter-gy
approved these changes
Jul 9, 2026
Contributor
|
🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.23.14-dev46 |
mscolnick
added a commit
that referenced
this pull request
Jul 9, 2026
…oop (#10124) The cache-export change (#9897) added a blocking join(timeout=5) to close_kernel to let the kernel flush pending work. But close_kernel runs synchronously on the event loop when the live edit server closes a session (restart_session, websocket disconnect), so the wait stalled the server for up to 5s. This broke the playwright suite: the toggle-cell test's kernel restart froze the server past the 5000ms click timeout and triggered 'Invalid session id' races. Make the graceful stop-and-join opt-in (graceful=False by default); only the export path (run_app_until_completion) enables it, where blocking is fine and the flushed cache manifest is needed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📝 Summary
Expands
marimo export html-wasm --executeto leverage[tools.marimo.runtime] cache_cells = true.This flag is set on export, cell execution caching is enabled, and all cell content moved over to the public http store. The Dual store actives when in WASM and cache is served over http.
Screen.Recording.2026-07-08.at.4.39.03.PM.mov
closes #9327