mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-20 17:54:30 +08:00
retry up to 3 times when update user cloud settings
This commit is contained in:
@@ -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,115 +75,129 @@ 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
|
||||||
|
|
||||||
if err != nil {
|
// Retry up to 3 times
|
||||||
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())
|
for i := 0; i < 3; i++ {
|
||||||
return false, errs.Or(err, errs.ErrOperationFailed)
|
userApplicationCloudSettings, err = a.userAppCloudSettings.GetUserApplicationCloudSettingsByUid(c, uid)
|
||||||
}
|
|
||||||
|
|
||||||
oldApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting)
|
if err != nil {
|
||||||
|
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())
|
||||||
if userApplicationCloudSettings != nil {
|
return false, errs.Or(err, errs.ErrOperationFailed)
|
||||||
for _, setting := range userApplicationCloudSettings.Settings {
|
|
||||||
oldApplicationCloudSettingsMap[setting.SettingKey] = setting
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the full update settings are the same as the existing settings
|
oldApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting)
|
||||||
if userAppCloudSettingUpdateReq.FullUpdate {
|
lastUpdateTime := int64(0)
|
||||||
if len(userAppCloudSettingUpdateReq.Settings) == len(oldApplicationCloudSettingsMap) {
|
|
||||||
needUpdate := false
|
if userApplicationCloudSettings != nil {
|
||||||
|
for _, setting := range userApplicationCloudSettings.Settings {
|
||||||
|
oldApplicationCloudSettingsMap[setting.SettingKey] = setting
|
||||||
|
}
|
||||||
|
|
||||||
|
lastUpdateTime = userApplicationCloudSettings.UpdatedUnixTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the full update settings are the same as the existing settings
|
||||||
|
if userAppCloudSettingUpdateReq.FullUpdate {
|
||||||
|
if len(userAppCloudSettingUpdateReq.Settings) == len(oldApplicationCloudSettingsMap) {
|
||||||
|
needUpdate := false
|
||||||
|
|
||||||
|
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
||||||
|
oldSetting, exists := oldApplicationCloudSettingsMap[setting.SettingKey]
|
||||||
|
|
||||||
|
if !exists || oldSetting.SettingValue != setting.SettingValue {
|
||||||
|
needUpdate = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !needUpdate {
|
||||||
|
return false, errs.ErrNothingWillBeUpdated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // Check if the partial update settings are the same as the existing settings or the settings to update are not set to sync
|
||||||
|
needUpdate := true
|
||||||
|
|
||||||
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
||||||
oldSetting, exists := oldApplicationCloudSettingsMap[setting.SettingKey]
|
cloudSetting, exists := oldApplicationCloudSettingsMap[setting.SettingKey]
|
||||||
|
|
||||||
if !exists || oldSetting.SettingValue != setting.SettingValue {
|
if !exists {
|
||||||
needUpdate = true
|
needUpdate = false
|
||||||
break
|
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 {
|
||||||
|
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 (try count %d)", setting.SettingKey, setting.SettingValue, i+1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !needUpdate {
|
if !needUpdate {
|
||||||
return false, errs.ErrNothingWillBeUpdated
|
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 true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting)
|
||||||
|
var newApplicationCloudSettingSlice models.ApplicationCloudSettingSlice
|
||||||
|
|
||||||
|
if userAppCloudSettingUpdateReq.FullUpdate {
|
||||||
|
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 {
|
||||||
|
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 (try count %d)", uid, i+1)
|
||||||
|
newApplicationCloudSettingsMap = oldApplicationCloudSettingsMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // Check if the partial update settings are the same as the existing settings or the settings to update are not set to sync
|
|
||||||
needUpdate := true
|
|
||||||
|
|
||||||
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
||||||
cloudSetting, exists := oldApplicationCloudSettingsMap[setting.SettingKey]
|
newApplicationCloudSettingsMap[setting.SettingKey] = setting
|
||||||
|
}
|
||||||
|
|
||||||
|
for settingKey, setting := range newApplicationCloudSettingsMap {
|
||||||
|
settingType, exists := models.ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES[settingKey]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
needUpdate = false
|
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)
|
||||||
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" is not set to sync", setting.SettingKey)
|
|
||||||
} else if cloudSetting.SettingValue == setting.SettingValue {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !needUpdate {
|
|
||||||
log.Infof(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] no user application cloud settings need to update for user \"uid:%d\"", uid)
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newApplicationCloudSettingsMap := make(map[string]models.ApplicationCloudSetting)
|
|
||||||
var newApplicationCloudSettingSlice models.ApplicationCloudSettingSlice
|
|
||||||
|
|
||||||
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)
|
|
||||||
} else {
|
|
||||||
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)
|
|
||||||
newApplicationCloudSettingsMap = oldApplicationCloudSettingsMap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, setting := range userAppCloudSettingUpdateReq.Settings {
|
|
||||||
newApplicationCloudSettingsMap[setting.SettingKey] = setting
|
|
||||||
}
|
|
||||||
|
|
||||||
for settingKey, setting := range newApplicationCloudSettingsMap {
|
|
||||||
settingType, exists := models.ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES[settingKey]
|
|
||||||
|
|
||||||
if !exists {
|
|
||||||
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" is not supported to sync", settingKey)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_STRING {
|
|
||||||
// Do Nothing
|
|
||||||
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER {
|
|
||||||
_, err := utils.StringToFloat64(setting.SettingValue)
|
|
||||||
|
|
||||||
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)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN {
|
|
||||||
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)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_STRING_BOOLEAN_MAP {
|
|
||||||
var settingValueMap map[string]bool
|
|
||||||
err := json.Unmarshal([]byte(setting.SettingValue), &settingValueMap)
|
|
||||||
|
|
||||||
if err != nil {
|
if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_STRING {
|
||||||
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())
|
// Do Nothing
|
||||||
|
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER {
|
||||||
|
_, err := utils.StringToFloat64(setting.SettingValue)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN {
|
||||||
|
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\" (try count %d)", settingKey, setting.SettingValue, i+1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if settingType == models.USER_APPLICATION_CLOUD_SETTING_TYPE_STRING_BOOLEAN_MAP {
|
||||||
|
var settingValueMap map[string]bool
|
||||||
|
err := json.Unmarshal([]byte(setting.SettingValue), &settingValueMap)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log.Warnf(c, "[user_app_cloud_settings.ApplicationSettingsUpdateHandler] user application cloud setting key \"%s\" has unknown type \"%s\"", settingKey, settingType)
|
newApplicationCloudSettingSlice = append(newApplicationCloudSettingSlice, setting)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newApplicationCloudSettingSlice = append(newApplicationCloudSettingSlice, setting)
|
err = a.userAppCloudSettings.UpdateUserApplicationCloudSettings(c, uid, newApplicationCloudSettingSlice, userAppCloudSettingUpdateReq.FullUpdate, lastUpdateTime)
|
||||||
}
|
|
||||||
|
|
||||||
err = a.userAppCloudSettings.UpdateUserApplicationCloudSettings(c, uid, newApplicationCloudSettingSlice)
|
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())
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user