Skip to content

Commit b3787bd

Browse files
authored
Merge pull request #54 from tstromberg/net-recover
improve recovery from sleep
2 parents 25f14d6 + 6a97dc7 commit b3787bd

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

cmd/goose/main.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,11 +455,19 @@ func (app *App) updatePRs(ctx context.Context) {
455455

456456
// Update health status on success
457457
app.mu.Lock()
458+
previousFailures := app.consecutiveFailures
458459
app.lastSuccessfulFetch = time.Now()
459460
app.consecutiveFailures = 0
460461
app.lastFetchError = ""
461462
app.mu.Unlock()
462463

464+
// Restore normal tray icon after successful fetch
465+
if previousFailures > 0 {
466+
slog.Info("[RECOVERY] Network recovered, restoring tray icon",
467+
"previousFailures", previousFailures)
468+
}
469+
app.setTrayTitle()
470+
463471
// Update state atomically
464472
app.mu.Lock()
465473
// Log PRs that were removed (likely merged/closed)
@@ -584,11 +592,19 @@ func (app *App) updatePRsWithWait(ctx context.Context) {
584592

585593
// Update health status on success
586594
app.mu.Lock()
595+
previousFailures := app.consecutiveFailures
587596
app.lastSuccessfulFetch = time.Now()
588597
app.consecutiveFailures = 0
589598
app.lastFetchError = ""
590599
app.mu.Unlock()
591600

601+
// Restore normal tray icon after successful fetch
602+
if previousFailures > 0 {
603+
slog.Info("[RECOVERY] Network recovered, restoring tray icon",
604+
"previousFailures", previousFailures)
605+
}
606+
app.setTrayTitle()
607+
592608
// Update state
593609
app.mu.Lock()
594610
app.incoming = incoming

cmd/goose/main_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,50 @@ func TestMenuItemTitleTransition(t *testing.T) {
174174
_ = ctx // Unused in this test but would be used for real menu operations
175175
}
176176

177+
// TestTrayIconRestoredAfterNetworkRecovery tests that the tray icon is restored
178+
// to normal after network failures are resolved.
179+
func TestTrayIconRestoredAfterNetworkRecovery(t *testing.T) {
180+
ctx := context.Background()
181+
mock := &MockSystray{}
182+
app := &App{
183+
mu: sync.RWMutex{},
184+
stateManager: NewPRStateManager(time.Now().Add(-35 * time.Second)), // Past grace period
185+
blockedPRTimes: make(map[string]time.Time),
186+
hiddenOrgs: make(map[string]bool),
187+
seenOrgs: make(map[string]bool),
188+
browserRateLimiter: NewBrowserRateLimiter(30*time.Second, 5, defaultMaxBrowserOpensDay),
189+
systrayInterface: mock,
190+
menuInitialized: true,
191+
}
192+
193+
// Initial state - successful fetch with some PRs
194+
app.incoming = []PR{
195+
{Repository: "test/repo", Number: 1, NeedsReview: true, UpdatedAt: time.Now()},
196+
}
197+
app.setTrayTitle()
198+
initialTitle := mock.title
199+
if initialTitle != "🪿 1" {
200+
t.Errorf("Expected initial tray title '🪿 1', got %q", initialTitle)
201+
}
202+
203+
// Simulate network failure - updatePRs would set warning icon and return early
204+
app.consecutiveFailures = 3
205+
app.lastFetchError = "network timeout"
206+
// In the old code, rebuildMenu would be called but return early, never calling setTrayTitle()
207+
app.rebuildMenu(ctx)
208+
// The mock systray won't have the warning icon because rebuildMenu doesn't set it directly
209+
210+
// Simulate network recovery - this should restore the normal icon
211+
app.consecutiveFailures = 0
212+
app.lastFetchError = ""
213+
// With our fix, setTrayTitle() is now called after successful fetch
214+
app.setTrayTitle()
215+
recoveredTitle := mock.title
216+
if recoveredTitle != "🪿 1" {
217+
t.Errorf("Expected tray title to be restored to '🪿 1' after recovery, got %q", recoveredTitle)
218+
}
219+
}
220+
177221
// TestTrayTitleUpdates tests that the tray title updates correctly based on PR counts.
178222
func TestTrayTitleUpdates(t *testing.T) {
179223
app := &App{

0 commit comments

Comments
 (0)