retry up to 3 times when update user cloud settings

This commit is contained in:
MaysWind
2025-08-22 00:08:08 +08:00
parent 15e4ad00ee
commit 781c2d9044
2 changed files with 110 additions and 87 deletions
+29 -14
View File
@@ -2,6 +2,7 @@ package api
import ( import (
"encoding/json" "encoding/json"
"time"
"github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/errs"
@@ -74,19 +75,26 @@ func (a *UserApplicationCloudSettingsApi) ApplicationSettingsUpdateHandler(c *co
return false, errs.ErrNotPermittedToPerformThisAction return false, errs.ErrNotPermittedToPerformThisAction
} }
userApplicationCloudSettings, err := a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, uid) var userApplicationCloudSettings *models.UserApplicationCloudSetting
// Retry up to 3 times
for i := 0; i < 3; i++ {
userApplicationCloudSettings, err = a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, uid)
if err != nil { if err != nil {
log.Errorf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] failed to get latest user application cloud settings for user \"uid:%d\", because %s", uid, err.Error()) log.Errorf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] failed to get latest user application cloud settings for user \"uid:%d\" (try count %d), because %s", uid, i+1, err.Error())
return false, errs.Or(err, errs.ErrOperationFailed) return false, errs.Or(err, errs.ErrOperationFailed)
} }
oldApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting) oldApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting)
lastUpdateTime := int64(0)
if userApplicationCloudSettings != nil { if userApplicationCloudSettings != nil {
for _, setting := range userApplicationCloudSettings.Settings { for _, setting := range userApplicationCloudSettings.Settings {
oldApplicationCloudSettingsMap[setting.SettingKey] = setting oldApplicationCloudSettingsMap[setting.SettingKey] = setting
} }
lastUpdateTime = userApplicationCloudSettings.UpdatedUnixTime
} }
// Check if the full update settings are the same as the existing settings // Check if the full update settings are the same as the existing settings
@@ -115,16 +123,16 @@ func (a *UserApplicationCloudSettingsApi) ApplicationSettingsUpdateHandler(c *co
if !exists { if !exists {
needUpdate = false needUpdate = false
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" is not set to sync", setting.SettingKey) log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" is not set to sync (try count %d)", setting.SettingKey, i+1)
} else if cloudSetting.SettingValue == setting.SettingValue { } else if cloudSetting.SettingValue == setting.SettingValue {
needUpdate = false needUpdate = false
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" value \"%s\" is not changed, no need to update", setting.SettingKey, setting.SettingValue) log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" value \"%s\" is not changed, no need to update (try count %d)", setting.SettingKey, setting.SettingValue, i+1)
} }
} }
if !needUpdate { if !needUpdate {
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] no user application cloud settings need to update for user \"uid:%d\"", uid) log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] no user application cloud settings need to update for user \"uid:%d\" (try count %d)", uid, i+1)
return false, nil return true, nil
} }
} }
@@ -132,10 +140,10 @@ func (a *UserApplicationCloudSettingsApi) ApplicationSettingsUpdateHandler(c *co
var newApplicationCloudSettingSlice models.ApplicationCloudSettingSlice var newApplicationCloudSettingSlice models.ApplicationCloudSettingSlice
if userAppCloudSettingUpdateReq.FullUpdate { if userAppCloudSettingUpdateReq.FullUpdate {
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user \"uid:%d\" application cloud settings force update, will overwrite all existing settings", uid) log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user \"uid:%d\" application cloud settings force update, will overwrite all existing settings (try count %d)", uid, i+1)
} else { } else {
if len(oldApplicationCloudSettingsMap) > 0 { if len(oldApplicationCloudSettingsMap) > 0 {
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user \"uid:%d\" application cloud settings exists, try to merge it with request settings", uid) log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user \"uid:%d\" application cloud settings exists, try to merge it with request settings (try count %d)", uid, i+1)
newApplicationCloudSettingsMap = oldApplicationCloudSettingsMap newApplicationCloudSettingsMap = oldApplicationCloudSettingsMap
} }
} }
@@ -148,7 +156,7 @@ func (a *UserApplicationCloudSettingsApi) ApplicationSettingsUpdateHandler(c *co
settingType, exists := models.ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES[settingKey] settingType, exists := models.ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES[settingKey]
if !exists { if !exists {
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" is not supported to sync", settingKey) log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" is not supported to sync (try count %d)", settingKey, i+1)
continue continue
} }
@@ -158,12 +166,12 @@ func (a *UserApplicationCloudSettingsApi) ApplicationSettingsUpdateHandler(c *co
_, err := utils.StringToFloat64(setting.SettingValue) _, err := utils.StringToFloat64(setting.SettingValue)
if err != nil { if err != nil {
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid number value \"%s\"", settingKey, setting.SettingValue) log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid number value \"%s\" (try count %d)", settingKey, setting.SettingValue, i+1)
continue continue
} }
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN { } else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN {
if setting.SettingValue != "true" && setting.SettingValue != "false" { if setting.SettingValue != "true" && setting.SettingValue != "false" {
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid boolean value \"%s\"", settingKey, setting.SettingValue) log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid boolean value \"%s\" (try count %d)", settingKey, setting.SettingValue, i+1)
continue continue
} }
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_STRING_BOOLEAN_MAP { } else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_STRING_BOOLEAN_MAP {
@@ -171,18 +179,25 @@ func (a *UserApplicationCloudSettingsApi) ApplicationSettingsUpdateHandler(c *co
err := json.Unmarshal([]byte(setting.SettingValue), &settingValueMap) err := json.Unmarshal([]byte(setting.SettingValue), &settingValueMap)
if err != nil { if err != nil {
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid map value \"%s\", because %s", settingKey, setting.SettingValue, err.Error()) log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has invalid map value \"%s\" (try count %d), because %s", settingKey, setting.SettingValue, i+1, err.Error())
continue continue
} }
} else { } else {
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has unknown type \"%s\"", settingKey, settingType) log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has unknown type \"%s\" (try count %d)", settingKey, settingType, i+1)
continue continue
} }
newApplicationCloudSettingSlice = append(newApplicationCloudSettingSlice, setting) newApplicationCloudSettingSlice = append(newApplicationCloudSettingSlice, setting)
} }
err = a.userAppCloudSettings.UpdateUserApplicationCloudSettings(c, uid, newApplicationCloudSettingSlice) err = a.userAppCloudSettings.UpdateUserApplicationCloudSettings(c, uid, newApplicationCloudSettingSlice, userAppCloudSettingUpdateReq.FullUpdate, lastUpdateTime)
if err == nil {
break
}
time.Sleep(100 * time.Millisecond) // Wait for 100 milliseconds before retrying
}
if err != nil { if err != nil {
log.Errorf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] failed to update user application cloud settings for user \"uid:%d\", because %s", uid, err.Error()) log.Errorf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] failed to update user application cloud settings for user \"uid:%d\", because %s", uid, err.Error())
+11 -3
View File
@@ -9,6 +9,7 @@ import (
"github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/datastore" "github.com/mayswind/ezbookkeeping/pkg/datastore"
"github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/log"
"github.com/mayswind/ezbookkeeping/pkg/models" "github.com/mayswind/ezbookkeeping/pkg/models"
) )
@@ -45,7 +46,7 @@ func (s *UserApplicationCloudSettingsService) GetUserApplicationCloudSettingsByU
} }
// UpdateUserApplicationCloudSettings updates user application cloud settings // UpdateUserApplicationCloudSettings updates user application cloud settings
func (s *UserApplicationCloudSettingsService) UpdateUserApplicationCloudSettings(c core.Context, uid int64, settings models.ApplicationCloudSettingSlice) error { func (s *UserApplicationCloudSettingsService) UpdateUserApplicationCloudSettings(c core.Context, uid int64, settings models.ApplicationCloudSettingSlice, forceUpdate bool, lastUpdateTime int64) error {
if uid <= 0 { if uid <= 0 {
return errs.ErrUserIdInvalid return errs.ErrUserIdInvalid
} }
@@ -65,14 +66,21 @@ func (s *UserApplicationCloudSettingsService) UpdateUserApplicationCloudSettings
return err return err
} }
updatedRows := int64(0)
if !exists { if !exists {
_, err = sess.Insert(userApplicationCloudSetting) updatedRows, err = sess.Insert(userApplicationCloudSetting)
} else if forceUpdate || lastUpdateTime <= 0 {
updatedRows, err = sess.ID(uid).Cols("settings", "updated_unix_time").Update(userApplicationCloudSetting)
} else { } else {
_, err = sess.ID(uid).Cols("settings", "updated_unix_time").Update(userApplicationCloudSetting) updatedRows, err = sess.ID(uid).Cols("settings", "updated_unix_time").Where("updated_unix_time=?", lastUpdateTime).Update(userApplicationCloudSetting)
} }
if err != nil { if err != nil {
return err return err
} else if updatedRows < 1 {
log.Errorf(c, "[user_app_cloud_settings.UpdateUserApplicationCloudSettings] failed to update user application cloud settings")
return errs.ErrDatabaseOperationFailed
} }
return nil return nil