detached a5ed4a4

refactor(cache): add completion channel to InvalidateAndRefresh

commit
a5ed4a4372b6297c65b7e8c10689d2daff072096
author
bnema · · 2025-11-30 05:00 UTC
parent
a35624f
signature
unsigned
2 files · +9 -6
M internal/cache/fuzzy_cache.go +6 -1
@@ -209,8 +209,12 @@ func (cm *CacheManager) buildCacheFromDB(ctx context.Context) (*DmenuFuzzyCache,
209209
210210 // InvalidateAndRefresh forces cache invalidation and refresh.
211211 // This should be called when we know the DB has changed (e.g., after adding history).
212-func (cm *CacheManager) InvalidateAndRefresh(ctx context.Context) {
212+// Returns a channel that is closed when the refresh is complete (can be ignored by callers).
213+func (cm *CacheManager) InvalidateAndRefresh(ctx context.Context) <-chan struct{} {
214+ done := make(chan struct{})
213215 go func() {
216+ defer close(done)
217+
214218 cm.mu.Lock()
215219 defer cm.mu.Unlock()
216220
@@ -229,6 +233,7 @@ func (cm *CacheManager) InvalidateAndRefresh(ctx context.Context) {
229233 logging.Warn(fmt.Sprintf("failed to refresh cache: %v", err))
230234 }
231235 }()
236+ return done
232237 }
233238
234239 // OnApplicationExit should be called when the application is about to exit.
@@ -209,8 +209,12 @@ func (cm *CacheManager) buildCacheFromDB(ctx context.Context) (*DmenuFuzzyCache,
209 209
210 // InvalidateAndRefresh forces cache invalidation and refresh.210 // InvalidateAndRefresh forces cache invalidation and refresh.
211 // This should be called when we know the DB has changed (e.g., after adding history).211 // This should be called when we know the DB has changed (e.g., after adding history).
212-func (cm *CacheManager) InvalidateAndRefresh(ctx context.Context) {212+// Returns a channel that is closed when the refresh is complete (can be ignored by callers).
213+func (cm *CacheManager) InvalidateAndRefresh(ctx context.Context) <-chan struct{} {
214+ done := make(chan struct{})
213 go func() {215 go func() {
216+ defer close(done)
217+
214 cm.mu.Lock()218 cm.mu.Lock()
215 defer cm.mu.Unlock()219 defer cm.mu.Unlock()
216 220
@@ -229,6 +233,7 @@ func (cm *CacheManager) InvalidateAndRefresh(ctx context.Context) {
229 logging.Warn(fmt.Sprintf("failed to refresh cache: %v", err))233 logging.Warn(fmt.Sprintf("failed to refresh cache: %v", err))
230 }234 }
231 }()235 }()
236+ return done
232 }237 }
233 238
234 // OnApplicationExit should be called when the application is about to exit.239 // OnApplicationExit should be called when the application is about to exit.
M internal/cache/fuzzy_cache_test.go +3 -5
@@ -521,11 +521,9 @@ func TestCacheInvalidation(t *testing.T) {
521521 t.Errorf("Expected 3 entries in initial cache, got %d", cache1.entryCount)
522522 }
523523
524- // Invalidate and refresh
525- manager.InvalidateAndRefresh(ctx)
526-
527- // Wait for background refresh
528- time.Sleep(100 * time.Millisecond)
524+ // Invalidate and refresh - wait for completion to prevent mock access after test ends
525+ done := manager.InvalidateAndRefresh(ctx)
526+ <-done
529527
530528 // Get updated cache
531529 cache2, err := manager.GetCache(ctx)
@@ -521,11 +521,9 @@ func TestCacheInvalidation(t *testing.T) {
521 t.Errorf("Expected 3 entries in initial cache, got %d", cache1.entryCount)521 t.Errorf("Expected 3 entries in initial cache, got %d", cache1.entryCount)
522 }522 }
523 523
524- // Invalidate and refresh524+ // Invalidate and refresh - wait for completion to prevent mock access after test ends
525- manager.InvalidateAndRefresh(ctx)525+ done := manager.InvalidateAndRefresh(ctx)
526-526+ <-done
527- // Wait for background refresh
528- time.Sleep(100 * time.Millisecond)
529 527
530 // Get updated cache528 // Get updated cache
531 cache2, err := manager.GetCache(ctx)529 cache2, err := manager.GetCache(ctx)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close