Merge branch 'main' into fix-monitor
Amp-Thread-ID: https://ampcode.com/threads/T-7bbd9558-2eb4-483a-bf7b-c61ea9c22092 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -210,7 +210,10 @@ func (s *Server) handleConnection(conn net.Conn) {
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("invalid request: %v", err),
|
||||
}
|
||||
s.writeResponse(writer, resp)
|
||||
if err := s.writeResponse(writer, resp); err != nil {
|
||||
// Connection broken, stop handling this connection
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -220,15 +223,32 @@ func (s *Server) handleConnection(conn net.Conn) {
|
||||
}
|
||||
|
||||
resp := s.handleRequest(&req)
|
||||
s.writeResponse(writer, resp)
|
||||
if err := s.writeResponse(writer, resp); err != nil {
|
||||
// Connection broken, stop handling this connection
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) writeResponse(writer *bufio.Writer, resp Response) {
|
||||
data, _ := json.Marshal(resp)
|
||||
_, _ = writer.Write(data)
|
||||
_ = writer.WriteByte('\n')
|
||||
_ = writer.Flush()
|
||||
func (s *Server) writeResponse(writer *bufio.Writer, resp Response) error {
|
||||
data, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal response: %w", err)
|
||||
}
|
||||
|
||||
if _, err := writer.Write(data); err != nil {
|
||||
return fmt.Errorf("failed to write response: %w", err)
|
||||
}
|
||||
|
||||
if err := writer.WriteByte('\n'); err != nil {
|
||||
return fmt.Errorf("failed to write newline: %w", err)
|
||||
}
|
||||
|
||||
if err := writer.Flush(); err != nil {
|
||||
return fmt.Errorf("failed to flush response: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) handleShutdown(_ *Request) Response {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -113,6 +114,15 @@ func New(path string) (*SQLiteStorage, error) {
|
||||
if isInMemory {
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(1)
|
||||
} else {
|
||||
// For file-based databases in daemon mode, limit connection pool to prevent
|
||||
// connection exhaustion under concurrent load. SQLite WAL mode supports
|
||||
// 1 writer + unlimited readers, but we limit to prevent goroutine pile-up
|
||||
// on write lock contention (bd-qhws).
|
||||
maxConns := runtime.NumCPU() + 1 // 1 writer + N readers
|
||||
db.SetMaxOpenConns(maxConns)
|
||||
db.SetMaxIdleConns(2)
|
||||
db.SetConnMaxLifetime(0) // SQLite doesn't need connection recycling
|
||||
}
|
||||
|
||||
// For file-based databases, enable WAL mode once after opening the connection.
|
||||
@@ -1134,11 +1144,11 @@ func (s *SQLiteStorage) findAllDependentsRecursive(ctx context.Context, tx *sql.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var depID string
|
||||
if err := rows.Scan(&depID); err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
if !result[depID] {
|
||||
@@ -1147,10 +1157,8 @@ func (s *SQLiteStorage) findAllDependentsRecursive(ctx context.Context, tx *sql.
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
_ = rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
_ = rows.Close()
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
||||
@@ -37,6 +37,14 @@ func ParseIssueID(input string, prefix string) string {
|
||||
// - No issue found matching the ID
|
||||
// - Multiple issues match (ambiguous prefix)
|
||||
func ResolvePartialID(ctx context.Context, store storage.Storage, input string) (string, error) {
|
||||
// Fast path: if the user typed an exact ID that exists, return it as-is.
|
||||
// This preserves behavior where issue IDs may not match the configured
|
||||
// issue_prefix (e.g. cross-repo IDs like "ao-izl"), while still allowing
|
||||
// prefix-based and hash-based resolution for other inputs.
|
||||
if issue, err := store.GetIssue(ctx, input); err == nil && issue != nil {
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// Get the configured prefix
|
||||
prefix, err := store.GetConfig(ctx, "issue_prefix")
|
||||
if err != nil || prefix == "" {
|
||||
@@ -63,7 +71,7 @@ func ResolvePartialID(ctx context.Context, store storage.Storage, input string)
|
||||
normalizedID = prefixWithHyphen + input
|
||||
}
|
||||
|
||||
// First try exact match
|
||||
// First try exact match on normalized ID
|
||||
issue, err := store.GetIssue(ctx, normalizedID)
|
||||
if err == nil && issue != nil {
|
||||
return normalizedID, nil
|
||||
|
||||
Reference in New Issue
Block a user