Repository navigation
Serialize production frontend work sharing one .web directory - #7453
FarhanAliRaza wants to merge 3 commits into
Conversation
Two exports (or an export and a prod/preview start) in the same project used to race on .web: the second replaced build/ and env.json while the first was still compiling or zipping, so one of them shipped the other's frontend. Hold an exclusive, reentrant file lock on .web/.reflex-build.lock from compilation through ZIP creation, release it before serving, and never create .web for a backend-only export that has nothing to protect. Split out of #7054 (lock only; the opt-in build cache that needs it follows separately). Claude-Session: https://claude.ai/code/session_018nWB9r2HcC5tkT72UxWgGj
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
All reported issues were addressed across 8 files
Reply with feedback, questions, or to request a fix.
Turn on auto-fix | Re-trigger cubic
💡 Codex ReviewLine 69 in b7d35ca .web
When a backend-only export starts while ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Merging this PR will improve performance by 5.73%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ⚡ | test_route_argument_extraction |
121.4 µs | 113.4 µs | +7.11% |
| ⚡ | test_from_event_type[event_spec] |
97.3 µs | 93.2 µs | +4.37% |
Tip
Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.
Comparing farhan/frontend-workspace-lock (a639b01) with main (d2528ac)
Footnotes
-
18 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
Brings in #7449, which drops Python 3.10 and moves ruff to py311. Claude-Session: https://claude.ai/code/session_01PXcFKAgnzhgdnSvhuCmxWE
PERF203 only applies before Python 3.11, where try/except in a loop costs per iteration. With ruff targeting py311 since #7449 the directive is unused, which RUF100 rejects. Claude-Session: https://claude.ai/code/session_01PXcFKAgnzhgdnSvhuCmxWE
masenf
left a comment
There was a problem hiding this comment.
should consolidate locking implementation with existing json_file_lock so we don't have multiple code paths handling platform-specific file locking in slightly different ways
Split out of #7054. This is the lock only; the opt-in build cache that motivated it is #7455 and is stacked on this.
Problem
Two production exports in the same project (or an export racing a
reflex run --env prodstart) share.web: the second one rewritesenv.json,build/, and the compiled sources while the first is still compiling or zipping, so one of them ships the other's frontend. Review bots on #7054 flagged this for the cache, but it is a pre-existing race.Changes
reflex/utils/build_lock.py: an exclusive, reentrant, per-.webfile lock on.web/.reflex-build.lock(flockon POSIX,msvcrt.lockingwith a 100 ms poll on Windows). Nested calls in one thread reuse the lock; forked children drop inherited ownership; a symlinked or non-regular lock path is refused instead of silently proceeding unlocked.export.export()holds it from configuration through ZIP creation. A backend-only export takes it only when.webalready exists (it archives.web/backend), and never creates.web._run_prod/_run_previewhold it through compile and build and release it before serving.Measurement
No speedup is claimed. Lock overhead on an unchanged bun export, repeat runs:
This is pure complexity in service of correctness (and of #7455). If the cache is not wanted, the question for this one is only whether the race above is worth fixing.
Measurement setup
Five-page app from the
blanktemplate (Radix Themes + Tailwind v4 plugins), Linux x86_64, 4 vCPU, Python 3.14, Node 22.22, npm 10.9, bun 1.4.2. Each run is a fresh interpreter callingreflex.utils.export.export()the same wayreflex exportdoes; durations are the phase timings the export already reports to telemetry (compileincludes the dependency install). Medians of 3 runs unless noted. Vite dominates every export (~6.5 s); these numbers isolate the part this PR touches.Type of change
Checklist
tests/unitssuite passes locally except the 14reflex_bench/drivers/test_browser.pycases that need a Playwright browser launch, which fail identically on untouchedmainin this sandboxruff check,ruff format --check,codespell, andpyright reflex testspass locallyhttps://claude.ai/code/session_018nWB9r2HcC5tkT72UxWgGj