Missing a refresh is possible in `ReferenceManager`
- Dominant language
- Java
- Stars
- 3.6k
- Forks
- 1.4k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 88
Description
### Description
I think the code of `ReferenceManager.maybeRefresh()` might miss a refresh. It tries to avoid starting a refresh if another is already in progress. But I think it's racy:
1. Thread A calls `maybeRefresh()`. `refreshLock.tryLock` returns true and a refresh is started.
2. When thread A is just before `unlock`, thread B flushes a new generation and calls `maybeRefresh()` again. Thread B gets `false` from `refreshLock.tryLock()` and does nothing.
3. Thread A releases the lock
4. the new generation isn't loaded
I think this optimization is unnecessary and should be removed. The lock should be used only to avoid two threads reloading the same reader, but a refresh notification must not be lost. I think there are two usage scenarios here:
1. `maybeRefresh` is called periodically by a single thread
2. `maybeRefresh` called after a successful flush or commit: possible loss.
In scenario 1 there are unnecessary calls to `maybeRefresh`, but never concurrent calls. In scenario 2, there are no unnecessary calls, but calls can be concurrent.
### Version and environment details
Current `main` branch.
Contributor guide
Research direction
Start by locating ReferenceManager.maybeRefresh() and inspect how refreshLock.tryLock(), refresh initiation, and unlock interact with flush or commit notifications. Confirm whether a concurrent notification can be lost, then ensure refresh notifications are not dropped while retaining the lock's protection against duplicate reader reloads; add or update concurrency coverage for the reported sequence.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, search
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100