|
- package region_sync
-
- import (
- "fmt"
- "time"
-
- "github.com/QuantumNous/new-api/common"
- "github.com/QuantumNous/new-api/logger"
- "github.com/QuantumNous/new-api/model"
- "github.com/QuantumNous/new-api/setting/system_setting"
- "github.com/bytedance/gopkg/util/gopool"
- )
-
- // PushUserCreateToSlave 在 master 节点创建用户后,异步推送到 slave 节点
- func PushUserCreateToSlave(user *model.User) {
- settings := system_setting.GetRegionSyncSettings()
-
- if !settings.Enabled || !settings.IsMaster {
- return
- }
- if len(settings.SlaveEndpoints) == 0 || settings.SyncApiKey == "" {
- return
- }
-
- gopool.Go(func() {
- req := &SyncUserRequest{
- Username: user.Username,
- Email: user.Email,
- PasswordHash: user.Password, // 传输的是哈希值,非明文密码
- DisplayName: user.DisplayName,
- Quota: user.Quota,
- RemoteUserId: user.Id,
- Group: user.Group,
- AffCode: user.AffCode,
- }
-
- for _, endpoint := range settings.SlaveEndpoints {
- client := NewSyncClient(endpoint, settings.SyncApiKey)
- resp, err := client.SyncUserCreate(req)
- if err != nil {
- logSyncError("user", user.Username, endpoint, "", err)
- continue
- }
- if !resp.Success {
- logSyncError("user", user.Username, endpoint, resp.Error, nil)
- continue
- }
- logSyncSuccess("user", user.Username, user.Id, endpoint)
- }
-
- recordSyncLog(user.Id, 0, model.SyncTypeUserCreate, "")
- })
- }
-
- // PushQuotaUpdateToSlave 在 master 节点更新用户余额后,推送到 slave 节点
- func PushQuotaUpdateToSlave(userId int, quota int) {
- settings := system_setting.GetRegionSyncSettings()
- if !settings.Enabled || !settings.IsMaster {
- return
- }
- if len(settings.SlaveEndpoints) == 0 || settings.SyncApiKey == "" {
- return
- }
-
- logger.LogDebug(nil, "[RegionSync] PushQuotaUpdateToSlave: userId=%d, quota=%d, endpoints=%v", userId, quota, settings.SlaveEndpoints)
-
- gopool.Go(func() {
- for _, endpoint := range settings.SlaveEndpoints {
- client := NewSyncClient(endpoint, settings.SyncApiKey)
- resp, err := client.UpdateQuota(userId, quota)
- if err != nil {
- logSyncError("quota update", fmt.Sprintf("user %d", userId), endpoint, "", err)
- continue
- }
- if !resp.Success {
- logSyncError("quota update", fmt.Sprintf("user %d", userId), endpoint, resp.Error, nil)
- continue
- }
- logSyncSuccess("quota update", fmt.Sprintf("user %d", userId), 0, endpoint)
- }
- })
- }
-
- // logSyncError 记录同步错误日志
- func logSyncError(operation, target, endpoint string, errMsg string, err error) {
- if err != nil {
- common.SysError(fmt.Sprintf("[RegionSync] Failed to push %s %s to slave %s: %v", operation, target, endpoint, err))
- } else {
- common.SysError(fmt.Sprintf("[RegionSync] Slave %s rejected %s %s: %s", endpoint, operation, target, errMsg))
- }
- }
-
- // logSyncSuccess 记录同步成功日志
- func logSyncSuccess(operation, target string, id int, endpoint string) {
- if id > 0 {
- common.SysLog(fmt.Sprintf("[RegionSync] Successfully pushed %s %s (id=%d) to slave %s", operation, target, id, endpoint))
- } else {
- common.SysLog(fmt.Sprintf("[RegionSync] Successfully pushed %s %s to slave %s", operation, target, endpoint))
- }
- }
-
- // recordSyncLog 创建同步日志记录
- func recordSyncLog(userId, remoteUserId int, syncType string, requestId string) {
- syncLog := &model.QuotaSyncLog{
- UserId: userId,
- RemoteUserId: remoteUserId,
- SyncType: syncType,
- Direction: model.SyncDirectionCnToOv,
- Status: model.SyncStatusSuccess,
- RequestId: requestId,
- CreatedAt: time.Now().Unix(),
- }
- if err := model.CreateSyncLog(syncLog); err != nil {
- common.SysError(fmt.Sprintf("[RegionSync] Failed to create sync log: %v", err))
- }
- }
|