fix: retry critical writes and allow super login

This commit is contained in:
2026-01-08 17:37:42 +08:00
parent 8ac82aaeb0
commit 3c159a2e0f
4 changed files with 233 additions and 156 deletions

View File

@@ -5,6 +5,7 @@ import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"errors"
"io"
"mime/multipart"
"os"
@@ -24,6 +25,7 @@ import (
"quyun/v2/providers/storage"
"github.com/google/uuid"
"github.com/jackc/pgconn"
"go.ipao.vip/gen/types"
)
@@ -453,3 +455,57 @@ func (s *common) GetAssetURL(objectKey string) string {
url, _ := s.storage.SignURL("GET", objectKey, 1*time.Hour)
return url
}
func retryCriticalWrite(ctx context.Context, fn func() error) error {
backoffs := []time.Duration{
50 * time.Millisecond,
120 * time.Millisecond,
250 * time.Millisecond,
}
var lastErr error
for attempt := 0; attempt <= len(backoffs); attempt++ {
if err := fn(); err != nil {
if !shouldRetryWrite(err) {
return err
}
lastErr = err
if attempt >= len(backoffs) {
return err
}
// 事务冲突/死锁等短暂错误,等待后重试。
if ctx != nil {
select {
case <-ctx.Done():
return errorx.ErrServiceTimeout.WithCause(ctx.Err())
case <-time.After(backoffs[attempt]):
}
} else {
time.Sleep(backoffs[attempt])
}
continue
}
return nil
}
return lastErr
}
func shouldRetryWrite(err error) bool {
var appErr *errorx.AppError
if errors.As(err, &appErr) {
return false
}
return isTransientDBError(err)
}
func isTransientDBError(err error) bool {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
switch pgErr.Code {
case "40001", "40P01":
return true
}
}
return false
}