Skip to content

feat: add WatchLock to coordinate rebuilds with external readers#34

Merged
cecton merged 19 commits into
mainfrom
run-with-hooks
Apr 25, 2026
Merged

feat: add WatchLock to coordinate rebuilds with external readers#34
cecton merged 19 commits into
mainfrom
run-with-hooks

Conversation

@yozhgoor
Copy link
Copy Markdown
Member

@yozhgoor yozhgoor commented Apr 23, 2026

Summary

  • Add public WatchLock / WatchLockGuard types for coordinating rebuilds with external readers (e.g. HTTP handlers)
  • Add Watch::lock() to retrieve the watcher's shared lock handle
  • Watch::run() holds the write lock for the entire duration of each command sequence — readers calling WatchLock::acquire() block until the build finishes, including the very first one
  • Fix race condition: generation counter ensures stale CommandSucceeded messages from a killed build are ignored
  • Document lock lifecycle on Watch::lock() and Watch struct

Why

Allows consumers such as dev servers to block file-serving while a rebuild is in progress, without serving stale or mid-write artifacts. The lock handle is cloneable and Send + Sync, so it composes naturally with threaded HTTP handlers.

Related to rustminded/xtask-wasm#81

@yozhgoor yozhgoor changed the title feat: add Watch::run_with_hooks lifecycle callbacks feat: add Watch::run_with_lock and refactor run loop Apr 23, 2026
@yozhgoor yozhgoor changed the title feat: add Watch::run_with_lock and refactor run loop feat: add WatchLock and integrate watch/build locking into Watch::run Apr 24, 2026
Copy link
Copy Markdown
Member

@cecton cecton left a comment

Choose a reason for hiding this comment

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

In general: avoid adding pub "because I need it in xtask-wasm", think about what you want to expose or not in your public facing API (especially in libraries!). The more you expose, the more you have to maintain for stability. Any change to anything exposed forces you to make a major release because you are breaking the API contract.

Think of it as a contract you sign with someone. If you want to change it, you first need to break the contract with them before establishing a new one that replaces the old one. Otherwise you end up with 2 parties just acting with what they believe is the contract but they are not on the same page.

Comment thread src/lib.rs Outdated
Comment thread src/lib.rs Outdated
Comment thread src/lib.rs Outdated
Comment thread src/lib.rs Outdated
Comment thread src/lib.rs Outdated
Comment thread src/lib.rs Outdated
@yozhgoor yozhgoor changed the title feat: add WatchLock and integrate watch/build locking into Watch::run feat: add WatchLock-based coordination to Watch Apr 24, 2026
@yozhgoor yozhgoor requested a review from cecton April 24, 2026 11:43
Comment thread src/lib.rs Outdated
@yozhgoor yozhgoor requested a review from cecton April 25, 2026 10:18
Comment thread src/lib.rs
Comment thread src/lib.rs
Comment thread src/lib.rs
Comment thread src/lib.rs
@cecton cecton changed the title feat: add WatchLock-based coordination to Watch Add WatchLock to coordinate rebuilds with external readers Apr 25, 2026
cecton
cecton approved these changes Apr 25, 2026
@cecton cecton changed the title Add WatchLock to coordinate rebuilds with external readers feat: add WatchLock to coordinate rebuilds with external readers Apr 25, 2026
@cecton cecton merged commit 863b476 into main Apr 25, 2026
6 checks passed
@cecton cecton deleted the run-with-hooks branch April 25, 2026 16:29
cecton added a commit to rustminded/xtask-wasm that referenced this pull request Apr 25, 2026
## Summary

- Obtain the shared `WatchLock` from the configured watcher before
spawning the watch thread
- Pass the lock into the HTTP serving loop
- Acquire a read guard per request, after parsing the header, so file
reads cannot race with rebuild writes
- Re-export `WatchLock` and `WatchLockGuard` from `xtask-wasm` so
consumers don't need a direct `xtask-watch` dependency to name the types
- Document why `read_header` is intentionally called before acquiring
the lock (connections are accepted and headers parsed during a build,
reducing response latency once it finishes)

## Why

Without coordination, a browser refresh mid-rebuild could receive
incomplete or inconsistent dist artifacts. Using the shared watcher lock
ensures the dev server only serves files once the current build has
fully written its output.

Closes #80
Requires rustminded/xtask-watch#34

---------

Co-authored-by: Cecile Tonglet <cecile.tonglet@cecton.com>
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.

2 participants