Make UserConfig mutations atomic across azd processes
- Dominant language
- Go
- Stars
- 569
- Forks
- 364
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 136
Description
### Summary
UserConfig is loaded once when an `azd` process starts, and later `Set`/`Unset` operations save that in-memory snapshot. If another process updates `~/.azd/config.json` in the meantime, the stale writer can overwrite those changes.
Extension stores that read, modify, and replace a shared map can also lose entries written concurrently. This already affects foreground agent session/conversation persistence; resumable invoke cursor persistence increases the frequency and duration of exposure.
### Expected behavior
UserConfig mutations should not overwrite unrelated changes made by another `azd` process, and concurrent updates to different entries in a shared extension store should be preserved.
### Proposed direction
- Serialize UserConfig mutations with a cross-process file lock.
- Reload the latest config while holding the lock.
- Apply the requested mutation and save atomically.
- Provide atomic map-entry mutation semantics, or a dedicated locked state store, for opaque extension keys.
- Add concurrency tests covering unrelated config paths and different entries in the session, conversation, and background-response stores.
### Context
Follow-up from #9703. Issue #9676 explicitly leaves cross-process races as a future optimization.
Contributor guide
Assessment
This issue has not been assessed yet.