77 app_errors "gpt-load/internal/errors"
88 "gpt-load/internal/models"
99 "gpt-load/internal/store"
10+ "math/rand"
1011 "strconv"
12+ "strings"
1113 "time"
1214
1315 "github.com/sirupsen/logrus"
@@ -88,6 +90,33 @@ func (p *KeyProvider) UpdateStatus(apiKey *models.APIKey, group *models.Group, i
8890 }()
8991}
9092
93+ // executeTransactionWithRetry wraps a database transaction with a retry mechanism.
94+ func (p * KeyProvider ) executeTransactionWithRetry (operation func (tx * gorm.DB ) error ) error {
95+ const maxRetries = 3
96+ const baseDelay = 50 * time .Millisecond
97+ const maxJitter = 150 * time .Millisecond
98+ var err error
99+
100+ for i := range maxRetries {
101+ err = p .db .Transaction (operation )
102+ if err == nil {
103+ return nil
104+ }
105+
106+ if strings .Contains (err .Error (), "database is locked" ) {
107+ jitter := time .Duration (rand .Intn (int (maxJitter )))
108+ totalDelay := baseDelay + jitter
109+ logrus .Debugf ("Database is locked, retrying in %v... (attempt %d/%d)" , totalDelay , i + 1 , maxRetries )
110+ time .Sleep (totalDelay )
111+ continue
112+ }
113+
114+ break
115+ }
116+
117+ return err
118+ }
119+
91120func (p * KeyProvider ) handleSuccess (keyID uint , keyHashKey , activeKeysListKey string ) error {
92121 keyDetails , err := p .store .HGetAll (keyHashKey )
93122 if err != nil {
@@ -101,7 +130,7 @@ func (p *KeyProvider) handleSuccess(keyID uint, keyHashKey, activeKeysListKey st
101130 return nil
102131 }
103132
104- return p .db . Transaction (func (tx * gorm.DB ) error {
133+ return p .executeTransactionWithRetry (func (tx * gorm.DB ) error {
105134 var key models.APIKey
106135 if err := tx .Set ("gorm:query_option" , "FOR UPDATE" ).First (& key , keyID ).Error ; err != nil {
107136 return fmt .Errorf ("failed to lock key %d for update: %w" , keyID , err )
@@ -149,7 +178,7 @@ func (p *KeyProvider) handleFailure(apiKey *models.APIKey, group *models.Group,
149178 // 获取该分组的有效配置
150179 blacklistThreshold := group .EffectiveConfig .BlacklistThreshold
151180
152- return p .db . Transaction (func (tx * gorm.DB ) error {
181+ return p .executeTransactionWithRetry (func (tx * gorm.DB ) error {
153182 var key models.APIKey
154183 if err := tx .Set ("gorm:query_option" , "FOR UPDATE" ).First (& key , apiKey .ID ).Error ; err != nil {
155184 return fmt .Errorf ("failed to lock key %d for update: %w" , apiKey .ID , err )
0 commit comments