iOS 模拟器构建缓存的跨进程并发仲裁(dev+packaged 双开 / --passive 多开)
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 401
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
### 使用场景 / Use case
dev 与 packaged 共库双开、或 dev --passive 多开时,多个 Desktop 进程共享同一 userData 下的 iOS 模拟器构建缓存。
### 当前问题 / Current limitation
PR #2899 的构建缓存复用(DerivedData + SPM checkout 按 worktree+arch 共享)用进程内 `activeBuildCacheKeys` 做互斥,但该 Set 只存在于单个 `createIOSSimulatorHost` 内,跨进程不共享。两个进程同时 build 同一 worktree 会并发写同一 DerivedData(build.db SQLite)导致锁冲突/损坏;prune 也看不到另一进程的 active builds / live artifacts。
### 期望方案 / Proposed solution
**复用既有的 O_EXLOCK 咨询锁(`acquireDarwinWriterLease`)给每个缓存 key 加跨进程锁。**
`ownership-registry-file.ts` 已有一套成熟的 `acquireDarwinWriterLease`(`openSync(..., O_NONBLOCK | O_EXLOCK)`,非阻塞 try-lock;内核在进程退出/崩溃时自动释放 fd —— 无 stale-lock、无 PID 复用边角)。把这个原语复用到缓存 key:
1. **锁文件独立目录**:`userData/ios-simulator/locks/.lock`(与 `projects/`、`spm/` 分离,避免被 prune 的 rename/rm 误删)。
2. **build 前抢锁**:对 `.lock` try-acquire;失败(另一进程持有)→ 抛 `DEVICE_BUSY`。成功后持有 fd 直到 build 结束(finally `release()`)。
3. **prune 跳过有锁 key**:prune 对每个候选 cache key 的 lock 文件 try-acquire,能拿到(= 无任何进程在用)才允许回收,检查完立即 release。跨进程 active build 因此不会被删。
4. **崩溃自恢复**:O_EXLOCK 由内核随进程退出自动释放,无需显式清理。
5. **非 Darwin 自然退化**:`acquireDarwinWriterLease` 非 Darwin 返回 null(iOS simulator 本就 Darwin-only),退回现有进程内互斥,行为不变。
### 已考虑的替代方案 / Alternatives considered
- **进程内 pid / 随机 salt 分域**:会让「进程重启后缓存失效」变成确定性高频代价(每次重启重编),破坏缓存复用核心价值 —— 不可取。
- **lockfile + PID 陈旧检测**:需处理 PID 复用、崩溃残留等边角;O_EXLOCK 内核托管更稳,且仓库已有现成原语。
- **只靠既有 SQLite WAL**:只保护 build.db,不保护 DerivedData 目录树 / SPM checkout 的并发写。
Contributor guide
Research direction
Start with ownership-registry-file.ts and the createIOSSimulatorHost entry point, then trace the shared cache and prune paths introduced by PR #2899. Exercise concurrent dev/packaged or --passive processes using the same cache key. Done means cross-process builds are serialized, DEVICE_BUSY is reported when appropriate, prune skips locked keys, and non-Darwin behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- build-system, mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100