Skip to content

fix(task-persistence): add cross-instance lock for concurrent task history updates (#920)#4

Closed
easonLiangWorldedtech wants to merge 1 commit into
mainfrom
fix/920-concurrent-task-history-cross-instance
Closed

fix(task-persistence): add cross-instance lock for concurrent task history updates (#920)#4
easonLiangWorldedtech wants to merge 1 commit into
mainfrom
fix/920-concurrent-task-history-cross-instance

Conversation

@easonLiangWorldedtech

@easonLiangWorldedtech easonLiangWorldedtech commented Jul 17, 2026

Copy link
Copy Markdown
Owner

[BUG] Concurrent task history updates from parallel tabs may cause lost entries

Problem

updateTaskHistory() has serialization within a single ClineProvider instance (see ClineProvider.taskHistory.spec.ts), but when two parallel tabs (different ClineProvider instances) call updateTaskHistory() concurrently, there may be a race condition that causes task history entries to be overwritten or lost.

Root Cause

PR Zoo-Code-Org#909 created an independent viewLocalState buffer for each ClineProvider instance, but the serialization logic in updateTaskHistory() only protects concurrent calls within the same instance. If two parallel tabs (different instances) call updateTaskHistory() simultaneously:

  1. Tab A: updateTaskHistory(taskX) → reads current state
  2. Tab B: updateTaskHistory(taskY) → reads same stale state (before Tab A's write)
  3. Tab A: writes taskX to history
  4. Tab B: writes taskY to history — may overwrite Tab A's entry

Fix

Add a global file-level lock (_history.lock) via proper-lockfile in TaskHistoryStore.withLock() so that mutations from different ClineProvider instances (parallel tabs) are serialized, preventing stale-cache overwrites.

Changes

  • Import proper-lockfile and add getGlobalLockFilePath() helper
  • Acquire global lock in withLock() before in-process serialization
  • Add 3 new cross-instance tests: concurrent updates, 5+ concurrent writes, and concurrent update + delete across tabs

Testing Requirements

  1. ✅ New test: "serializes concurrent updateTaskHistory from two parallel instances" — verifies same task updated concurrently produces consistent final state
  2. ✅ New test: "handles 5+ concurrent updates from different tabs without losing entries" — stress test with 12 concurrent writes
  3. ✅ New test: "concurrent updateTaskHistory + deleteTaskFromState across tabs" — mixed operations

Related Issues

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