fix(storage): race condition when reconnect closes db mid-query (GH#607)

Change reconnectMu from sync.Mutex to sync.RWMutex so read operations
can hold RLock during database access. This prevents reconnect() from
closing the connection while queries are in progress.

- GetIssue and SearchIssues now hold RLock during database operations
- Close() acquires write lock to coordinate with reconnect
- Add TestConcurrentReadsWithReconnect to verify the fix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-18 11:27:58 -08:00
parent e0d8abe8c3
commit 6087cd438b
3 changed files with 155 additions and 1 deletions

View File

@@ -227,6 +227,11 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue,
// Check for external database file modifications (daemon mode)
s.checkFreshness()
// Hold read lock during database operations to prevent reconnect() from
// closing the connection mid-query (GH#607 race condition fix)
s.reconnectMu.RLock()
defer s.reconnectMu.RUnlock()
var issue types.Issue
var closedAt sql.NullTime
var estimatedMinutes sql.NullInt64
@@ -1400,6 +1405,11 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t
// Check for external database file modifications (daemon mode)
s.checkFreshness()
// Hold read lock during database operations to prevent reconnect() from
// closing the connection mid-query (GH#607 race condition fix)
s.reconnectMu.RLock()
defer s.reconnectMu.RUnlock()
whereClauses := []string{}
args := []interface{}{}