fix(usage): 使用日志事务和幂等性修复
- UsageLogRepository.Create 返回 inserted 标志 - UsageService 使用事务保证原子性 - 避免重复扣费(幂等重试场景) - 更新依赖注入和测试
This commit is contained in:
@@ -61,9 +61,16 @@ func (r *usageLogRepository) getPerformanceStats(ctx context.Context, userID int
|
||||
return requestCount / 5, tokenCount / 5, nil
|
||||
}
|
||||
|
||||
func (r *usageLogRepository) Create(ctx context.Context, log *service.UsageLog) error {
|
||||
func (r *usageLogRepository) Create(ctx context.Context, log *service.UsageLog) (bool, error) {
|
||||
if log == nil {
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// 在事务上下文中,使用 tx 绑定的 ExecQuerier 执行原生 SQL,保证与其他更新同事务。
|
||||
// 无事务时回退到默认的 *sql.DB 执行器。
|
||||
sqlq := r.sql
|
||||
if tx := dbent.TxFromContext(ctx); tx != nil {
|
||||
sqlq = tx.Client()
|
||||
}
|
||||
|
||||
createdAt := log.CreatedAt
|
||||
@@ -152,18 +159,20 @@ func (r *usageLogRepository) Create(ctx context.Context, log *service.UsageLog)
|
||||
firstToken,
|
||||
createdAt,
|
||||
}
|
||||
if err := scanSingleRow(ctx, r.sql, query, args, &log.ID, &log.CreatedAt); err != nil {
|
||||
if err := scanSingleRow(ctx, sqlq, query, args, &log.ID, &log.CreatedAt); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) && requestID != "" {
|
||||
selectQuery := "SELECT id, created_at FROM usage_logs WHERE request_id = $1 AND api_key_id = $2"
|
||||
if err := scanSingleRow(ctx, r.sql, selectQuery, []any{requestID, log.ApiKeyID}, &log.ID, &log.CreatedAt); err != nil {
|
||||
return err
|
||||
if err := scanSingleRow(ctx, sqlq, selectQuery, []any{requestID, log.ApiKeyID}, &log.ID, &log.CreatedAt); err != nil {
|
||||
return false, err
|
||||
}
|
||||
log.RateMultiplier = rateMultiplier
|
||||
return false, nil
|
||||
} else {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
log.RateMultiplier = rateMultiplier
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (r *usageLogRepository) GetByID(ctx context.Context, id int64) (log *service.UsageLog, err error) {
|
||||
|
||||
Reference in New Issue
Block a user