Add per-project shared lock to avoid fetch collisions

Introduce a singleton ProjectsLock to coordinate fetches across sources
on a per-project basis without blocking. FetchOne now tries to acquire a
non-blocking lock for the project before proceeding; if the lock is busy
we reschedule the task to avoid colliding with an in-flight fetch. When
acquired, the lock is held via a try-with- resources token and we still
honor the async runway check.

Previous changes (I3c3d7b97, I7883e680) attempted to centralize
coordination with a shared projects queue, but it dropped the fetch
origin, which led to fetch events being lost. The new lock-based
approach keeps the source context intact and guarantees at most one
concurrent fetch per project across sources.

Bug: Issue 437805590
Change-Id: I2ce2f5a8532a7282f03f245f3670e8c318de0a61
5 files changed
tree: 1daed25245e08b2fc67097fa391bd819756e53bf
  1. example-setup/
  2. src/
  3. .gitignore
  4. BUILD
  5. Jenkinsfile
  6. LICENSE