fix(auth): tolerate concurrent demo-user seed unique conflicts

Parallel NewServer bootstrap raced with goose fixed-id user rows and
sequence drift, panicking the server package on wangzong insert. Treat
unique violations as success when the demo username exists (or retry once).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-22 18:18:33 +08:00
co-authored by Cursor
parent 675b00e06d
commit 0ebcabf7df
+34
View File
@@ -2,13 +2,25 @@ package auth
import (
"context"
"errors"
"fmt"
"os"
"strings"
"chat-agent-system/internal/config"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgxpool"
)
func isUniqueViolation(err error) bool {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) && pgErr.Code == "23505" {
return true
}
msg := err.Error()
return strings.Contains(msg, "23505") || strings.Contains(msg, "duplicate key")
}
// BootstrapAdminFromConfig 确保配置的管理员账户在 PG 中存在且具备 role-admin。
func BootstrapAdminFromConfig(ctx context.Context, store AuthStore, cfg *config.Config) error {
if store == nil || cfg == nil {
@@ -102,6 +114,28 @@ func BootstrapDevSeedUsers(ctx context.Context, store AuthStore, cfg *config.Con
EmployeeID: su.empID,
})
if err != nil {
// Concurrent NewServer bootstrap and sequence drift after fixed-id
// goose seeds can race on users_pkey/username. If the demo user
// exists afterwards, treat the seed as successful.
if _, getErr := store.GetUserByUsername(ctx, su.username); getErr == nil {
continue
}
if isUniqueViolation(err) {
if _, retryErr := store.CreateUser(ctx, &UserAccount{
Username: su.username,
Name: su.name,
PasswordHash: passHash,
Status: StatusActive,
RoleID: su.roleID,
Position: su.position,
Department: su.dept,
EmployeeID: su.empID,
}); retryErr == nil {
continue
} else if _, getErr := store.GetUserByUsername(ctx, su.username); getErr == nil {
continue
}
}
return fmt.Errorf("seed user %s: %w", su.username, err)
}
}