🎨 Improve kernel stability by eliminating some data races https://github.com/siyuan-note/siyuan/issues/9842

This commit is contained in:
Daniel 2023-12-08 21:46:46 +08:00
parent f9d476ebf5
commit 1d54de679f
No known key found for this signature in database
GPG key ID: 86211BA83DF03017
7 changed files with 83 additions and 62 deletions

View file

@ -452,7 +452,7 @@ func getCloudUser(c *gin.Context) {
token = t.(string)
}
model.RefreshUser(token)
ret.Data = model.Conf.User
ret.Data = model.Conf.GetUser()
}
func logoutCloudUser(c *gin.Context) {

View file

@ -387,7 +387,7 @@ func performSync(c *gin.Context) {
mobileSwitch = mobileSwitchArg.(bool)
}
if mobileSwitch {
if nil == model.Conf.User || !model.Conf.Sync.Enabled {
if nil == model.Conf.GetUser() || !model.Conf.Sync.Enabled {
return
}
}

View file

@ -39,7 +39,7 @@ import (
var ErrFailedToConnectCloudServer = errors.New("failed to connect cloud server")
func CloudChatGPT(msg string, contextMsgs []string) (ret string, stop bool, err error) {
if nil == Conf.User {
if nil == Conf.GetUser() {
return
}
@ -61,7 +61,7 @@ func CloudChatGPT(msg string, contextMsgs []string) (ret string, stop bool, err
request := httpclient.NewCloudRequest30s()
_, err = request.
SetSuccessResult(requestResult).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
SetBody(payload).
Post(util.GetCloudServer() + "/apis/siyuan/ai/chatGPT")
if nil != err {
@ -99,7 +99,7 @@ func CloudChatGPT(msg string, contextMsgs []string) (ret string, stop bool, err
}
func StartFreeTrial() (err error) {
if nil == Conf.User {
if nil == Conf.GetUser() {
return errors.New(Conf.Language(31))
}
@ -107,7 +107,7 @@ func StartFreeTrial() (err error) {
request := httpclient.NewCloudRequest30s()
_, err = request.
SetSuccessResult(requestResult).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/user/startFreeTrial")
if nil != err {
logging.LogErrorf("start free trial failed: %s", err)
@ -124,7 +124,7 @@ func DeactivateUser() (err error) {
request := httpclient.NewCloudRequest30s()
resp, err := request.
SetSuccessResult(requestResult).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/user/deactivate")
if nil != err {
logging.LogErrorf("deactivate user failed: %s", err)
@ -150,7 +150,7 @@ func SetCloudBlockReminder(id, data string, timed int64) (err error) {
resp, err := request.
SetSuccessResult(requestResult).
SetBody(payload).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/calendar/setBlockReminder")
if nil != err {
logging.LogErrorf("set block reminder failed: %s", err)
@ -182,7 +182,7 @@ func LoadUploadToken() (err error) {
request := httpclient.NewCloudRequest30s()
resp, err := request.
SetSuccessResult(requestResult).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/upload/token")
if nil != err {
logging.LogErrorf("get upload token failed: %s", err)
@ -228,8 +228,8 @@ func refreshSubscriptionExpirationRemind() {
defer logging.Recover()
if IsSubscriber() && -1 != Conf.User.UserSiYuanProExpireTime {
expired := int64(Conf.User.UserSiYuanProExpireTime)
if IsSubscriber() && -1 != Conf.GetUser().UserSiYuanProExpireTime {
expired := int64(Conf.GetUser().UserSiYuanProExpireTime)
now := time.Now().UnixMilli()
if now >= expired { // 已经过期
if now-expired <= 1000*60*60*24*2 { // 2 天内提醒 https://github.com/siyuan-note/siyuan/issues/7816
@ -240,7 +240,7 @@ func refreshSubscriptionExpirationRemind() {
}
remains := int((expired - now) / 1000 / 60 / 60 / 24)
expireDay := 15 // 付费订阅提前 15 天提醒
if 2 == Conf.User.UserSiYuanSubscriptionPlan {
if 2 == Conf.GetUser().UserSiYuanSubscriptionPlan {
expireDay = 3 // 试用订阅提前 3 天提醒
}
@ -256,10 +256,10 @@ func refreshSubscriptionExpirationRemind() {
func refreshUser() {
defer logging.Recover()
if nil != Conf.User {
if nil != Conf.GetUser() {
time.Sleep(2 * time.Minute)
if nil != Conf.User {
RefreshUser(Conf.User.UserToken)
if nil != Conf.GetUser() {
RefreshUser(Conf.GetUser().UserToken)
}
subscriptionExpirationReminded = false
}
@ -329,22 +329,22 @@ func RefreshUser(token string) {
threeDaysAfter := util.CurrentTimeMillis() + 1000*60*60*24*3
if "" == token {
if "" != Conf.UserData {
Conf.User = loadUserFromConf()
Conf.SetUser(loadUserFromConf())
}
if nil == Conf.User {
if nil == Conf.GetUser() {
return
}
var tokenExpireTime int64
tokenExpireTime, err := strconv.ParseInt(Conf.User.UserTokenExpireTime+"000", 10, 64)
tokenExpireTime, err := strconv.ParseInt(Conf.GetUser().UserTokenExpireTime+"000", 10, 64)
if nil != err {
logging.LogErrorf("convert token expire time [%s] failed: %s", Conf.User.UserTokenExpireTime, err)
logging.LogErrorf("convert token expire time [%s] failed: %s", Conf.GetUser().UserTokenExpireTime, err)
util.PushErrMsg(Conf.Language(19), 5000)
return
}
if threeDaysAfter > tokenExpireTime {
token = Conf.User.UserToken
token = Conf.GetUser().UserToken
goto Net
}
return
@ -354,15 +354,15 @@ Net:
start := time.Now()
user, err := getUser(token)
if err != nil {
if nil == Conf.User || errInvalidUser == err {
if nil == Conf.GetUser() || errInvalidUser == err {
util.PushErrMsg(Conf.Language(19), 5000)
return
}
var tokenExpireTime int64
tokenExpireTime, err = strconv.ParseInt(Conf.User.UserTokenExpireTime+"000", 10, 64)
tokenExpireTime, err = strconv.ParseInt(Conf.GetUser().UserTokenExpireTime+"000", 10, 64)
if nil != err {
logging.LogErrorf("convert token expire time [%s] failed: %s", Conf.User.UserTokenExpireTime, err)
logging.LogErrorf("convert token expire time [%s] failed: %s", Conf.GetUser().UserTokenExpireTime, err)
util.PushErrMsg(Conf.Language(19), 5000)
return
}
@ -374,7 +374,7 @@ Net:
return
}
Conf.User = user
Conf.SetUser(user)
data, _ := gulu.JSON.MarshalJSON(user)
Conf.UserData = util.AESEncrypt(string(data))
Conf.Save()
@ -407,7 +407,7 @@ func RemoveCloudShorthands(ids []string) (err error) {
}
resp, err := request.
SetSuccessResult(&result).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
SetBody(body).
Post(util.GetCloudServer() + "/apis/siyuan/inbox/removeCloudShorthands")
if nil != err {
@ -435,7 +435,7 @@ func GetCloudShorthand(id string) (ret map[string]interface{}, err error) {
request := httpclient.NewCloudRequest30s()
resp, err := request.
SetSuccessResult(&result).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/inbox/getCloudShorthand?id=" + id)
if nil != err {
logging.LogErrorf("get cloud shorthand failed: %s", err)
@ -475,7 +475,7 @@ func GetCloudShorthands(page int) (result map[string]interface{}, err error) {
request := httpclient.NewCloudRequest30s()
resp, err := request.
SetSuccessResult(&result).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/inbox/getCloudShorthands?p=" + strconv.Itoa(page))
if nil != err {
logging.LogErrorf("get cloud shorthands failed: %s", err)
@ -565,7 +565,7 @@ func UseActivationcode(code string) (err error) {
_, err = request.
SetSuccessResult(requestResult).
SetBody(map[string]string{"data": code}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/useActivationcode")
if nil != err {
logging.LogErrorf("check activation code failed: %s", err)
@ -586,7 +586,7 @@ func CheckActivationcode(code string) (retCode int, msg string) {
_, err := request.
SetSuccessResult(requestResult).
SetBody(map[string]string{"data": code}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Post(util.GetCloudServer() + "/apis/siyuan/checkActivationcode")
if nil != err {
logging.LogErrorf("check activation code failed: %s", err)
@ -650,6 +650,6 @@ func Login2fa(token, code string) (map[string]interface{}, error) {
func LogoutUser() {
Conf.UserData = ""
Conf.User = nil
Conf.SetUser(nil)
Conf.Save()
}

View file

@ -62,7 +62,7 @@ type AppConf struct {
Graph *conf.Graph `json:"graph"` // 关系图配置
UILayout *conf.UILayout `json:"uiLayout"` // 界面布局v2.8.0 后这个字段不再使用
UserData string `json:"userData"` // 社区用户信息,对 User 加密存储
User *conf.User `json:"-"` // 社区用户内存结构,不持久化
User *conf.User `json:"-"` // 社区用户内存结构,不持久化。不要直接使用,使用 GetUser() 和 SetUser() 方法
Account *conf.Account `json:"account"` // 帐号配置
ReadOnly bool `json:"readonly"` // 是否是以只读模式运行
LocalIPs []string `json:"localIPs"` // 本地 IP 列表
@ -80,6 +80,20 @@ type AppConf struct {
OpenHelp bool `json:"openHelp"` // 启动后是否需要打开用户指南
ShowChangelog bool `json:"showChangelog"` // 是否显示版本更新日志
CloudRegion int `json:"cloudRegion"` // 云端区域0中国大陆1北美
m *sync.Mutex
}
func (conf *AppConf) GetUser() *conf.User {
conf.m.Lock()
defer conf.m.Unlock()
return conf.User
}
func (conf *AppConf) SetUser(user *conf.User) {
conf.m.Lock()
defer conf.m.Unlock()
conf.User = user
}
func InitConf() {
@ -92,7 +106,7 @@ func InitConf() {
}
}
Conf = &AppConf{LogLevel: "debug"}
Conf = &AppConf{LogLevel: "debug", m: &sync.Mutex{}}
confPath := filepath.Join(util.ConfDir, "conf.json")
if gulu.File.IsExist(confPath) {
data, err := os.ReadFile(confPath)
@ -288,7 +302,7 @@ func InitConf() {
Conf.System.OSPlatform = util.GetOSPlatform()
if "" != Conf.UserData {
Conf.User = loadUserFromConf()
Conf.SetUser(loadUserFromConf())
}
if nil == Conf.Account {
Conf.Account = conf.NewAccount()
@ -736,14 +750,15 @@ func InitBoxes() {
}
func IsSubscriber() bool {
return nil != Conf.User && (-1 == Conf.User.UserSiYuanProExpireTime || 0 < Conf.User.UserSiYuanProExpireTime) && 0 == Conf.User.UserSiYuanSubscriptionStatus
u := Conf.GetUser()
return nil != u && (-1 == u.UserSiYuanProExpireTime || 0 < u.UserSiYuanProExpireTime) && 0 == u.UserSiYuanSubscriptionStatus
}
func IsPaidUser() bool {
if IsSubscriber() {
return true
}
return nil != Conf.User // Sign in to use S3/WebDAV data sync https://github.com/siyuan-note/siyuan/issues/8779
return nil != Conf.GetUser() // Sign in to use S3/WebDAV data sync https://github.com/siyuan-note/siyuan/issues/8779
// TODO S3/WebDAV data sync and backup are available for a fee https://github.com/siyuan-note/siyuan/issues/8780
// return nil != Conf.User && 1 == Conf.User.UserSiYuanOneTimePayStatus
}

View file

@ -84,7 +84,7 @@ func Export2Liandi(id string) (err error) {
request := httpclient.NewCloudRequest30s()
resp, getErr := request.
SetSuccessResult(result).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
Get(util.GetCloudAccountServer() + "/api/v2/article/update/" + articleId)
if nil != getErr {
logging.LogErrorf("get liandi article info failed: %s", getErr)
@ -114,7 +114,7 @@ func Export2Liandi(id string) (err error) {
title := path.Base(tree.HPath)
tags := tree.Root.IALAttr("tags")
content := exportMarkdownContent0(tree, util.GetCloudForumAssetsServer()+time.Now().Format("2006/01")+"/siyuan/"+Conf.User.UserId+"/", true,
content := exportMarkdownContent0(tree, util.GetCloudForumAssetsServer()+time.Now().Format("2006/01")+"/siyuan/"+Conf.GetUser().UserId+"/", true,
4, 1, 0,
"#", "#",
"", "",
@ -123,7 +123,7 @@ func Export2Liandi(id string) (err error) {
request := httpclient.NewCloudRequest30s()
request = request.
SetSuccessResult(result).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
SetCookies(&http.Cookie{Name: "symphony", Value: Conf.GetUser().UserToken}).
SetBody(map[string]interface{}{
"articleTitle": title,
"articleTags": tags,
@ -1090,7 +1090,7 @@ func ExportStdMarkdown(id string) string {
cloudAssetsBase := ""
if IsSubscriber() {
cloudAssetsBase = util.GetCloudAssetsServer() + Conf.User.UserId + "/"
cloudAssetsBase = util.GetCloudAssetsServer() + Conf.GetUser().UserId + "/"
}
return exportMarkdownContent0(tree, cloudAssetsBase, false,
Conf.Export.BlockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode,

View file

@ -989,9 +989,10 @@ func syncRepoDownload() (err error) {
logging.LogErrorf("sync data repo download failed: %s", err)
msg := fmt.Sprintf(Conf.Language(80), formatRepoErrorMsg(err))
if errors.Is(err, dejavu.ErrCloudStorageSizeExceeded) {
msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
if 2 == Conf.User.UserSiYuanSubscriptionPlan {
msg = fmt.Sprintf(Conf.Language(68), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
u := Conf.GetUser()
msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(u.UserSiYuanRepoSize)))
if 2 == u.UserSiYuanSubscriptionPlan {
msg = fmt.Sprintf(Conf.Language(68), humanize.Bytes(uint64(u.UserSiYuanRepoSize)))
}
}
Conf.Sync.Stat = msg
@ -1058,9 +1059,10 @@ func syncRepoUpload() (err error) {
logging.LogErrorf("sync data repo upload failed: %s", err)
msg := fmt.Sprintf(Conf.Language(80), formatRepoErrorMsg(err))
if errors.Is(err, dejavu.ErrCloudStorageSizeExceeded) {
msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
if 2 == Conf.User.UserSiYuanSubscriptionPlan {
msg = fmt.Sprintf(Conf.Language(68), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
u := Conf.GetUser()
msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(u.UserSiYuanRepoSize)))
if 2 == u.UserSiYuanSubscriptionPlan {
msg = fmt.Sprintf(Conf.Language(68), humanize.Bytes(uint64(u.UserSiYuanRepoSize)))
}
}
Conf.Sync.Stat = msg
@ -1146,9 +1148,10 @@ func bootSyncRepo() (err error) {
logging.LogErrorf("sync data repo failed: %s", err)
msg := fmt.Sprintf(Conf.Language(80), formatRepoErrorMsg(err))
if errors.Is(err, dejavu.ErrCloudStorageSizeExceeded) {
msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
if 2 == Conf.User.UserSiYuanSubscriptionPlan {
msg = fmt.Sprintf(Conf.Language(68), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
u := Conf.GetUser()
msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(u.UserSiYuanRepoSize)))
if 2 == u.UserSiYuanSubscriptionPlan {
msg = fmt.Sprintf(Conf.Language(68), humanize.Bytes(uint64(u.UserSiYuanRepoSize)))
}
}
Conf.Sync.Stat = msg
@ -1220,9 +1223,10 @@ func syncRepo(exit, byHand bool) (dataChanged bool, err error) {
logging.LogErrorf("sync data repo failed: %s", err)
msg := fmt.Sprintf(Conf.Language(80), formatRepoErrorMsg(err))
if errors.Is(err, dejavu.ErrCloudStorageSizeExceeded) {
msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
if 2 == Conf.User.UserSiYuanSubscriptionPlan {
msg = fmt.Sprintf(Conf.Language(68), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
u := Conf.GetUser()
msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(u.UserSiYuanRepoSize)))
if 2 == u.UserSiYuanSubscriptionPlan {
msg = fmt.Sprintf(Conf.Language(68), humanize.Bytes(uint64(u.UserSiYuanRepoSize)))
}
}
Conf.Sync.Stat = msg
@ -1762,9 +1766,10 @@ func buildCloudConf() (ret *cloud.Conf, err error) {
userId, token, availableSize := "0", "", int64(1024*1024*1024*1024*2)
if nil != Conf.User && conf.ProviderSiYuan == Conf.Sync.Provider {
userId = Conf.User.UserId
token = Conf.User.UserToken
availableSize = Conf.User.GetCloudRepoAvailableSize()
u := Conf.GetUser()
userId = u.UserId
token = u.UserToken
availableSize = u.GetCloudRepoAvailableSize()
}
ret = &cloud.Conf{
@ -1857,12 +1862,13 @@ func GetCloudSpace() (s *Sync, b *Backup, hSize, hAssetSize, hTotalSize, hExchan
b.HSize = humanize.Bytes(uint64(backupSize))
hAssetSize = humanize.Bytes(uint64(assetSize))
hSize = humanize.Bytes(uint64(totalSize))
hTotalSize = humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize))
hExchangeSize = humanize.Bytes(uint64(Conf.User.UserSiYuanPointExchangeRepoSize))
hTrafficUploadSize = humanize.Bytes(uint64(Conf.User.UserTrafficUpload))
hTrafficDownloadSize = humanize.Bytes(uint64(Conf.User.UserTrafficDownload))
hTrafficAPIGet = humanize.SIWithDigits(Conf.User.UserTrafficAPIGet, 2, "")
hTrafficAPIPut = humanize.SIWithDigits(Conf.User.UserTrafficAPIPut, 2, "")
u := Conf.GetUser()
hTotalSize = humanize.Bytes(uint64(u.UserSiYuanRepoSize))
hExchangeSize = humanize.Bytes(uint64(u.UserSiYuanPointExchangeRepoSize))
hTrafficUploadSize = humanize.Bytes(uint64(u.UserTrafficUpload))
hTrafficDownloadSize = humanize.Bytes(uint64(u.UserTrafficDownload))
hTrafficAPIGet = humanize.SIWithDigits(u.UserTrafficAPIGet, 2, "")
hTrafficAPIPut = humanize.SIWithDigits(u.UserTrafficAPIPut, 2, "")
}
return
}

View file

@ -739,7 +739,7 @@ func connectSyncWebSocket() {
reconnected := false
for retries := 0; retries < 7; retries++ {
time.Sleep(7 * time.Second)
if nil == Conf.User {
if nil == Conf.GetUser() {
return
}
@ -794,7 +794,7 @@ func dialSyncWebSocket() (c *websocket.Conn, err error) {
endpoint := util.GetCloudWebSocketServer() + "/apis/siyuan/dejavu/ws"
header := http.Header{
"User-Agent": []string{util.UserAgent},
"x-siyuan-uid": []string{Conf.User.UserId},
"x-siyuan-uid": []string{Conf.GetUser().UserId},
"x-siyuan-kernel": []string{KernelID},
"x-siyuan-ver": []string{util.Ver},
"x-siyuan-os": []string{runtime.GOOS},