diff --git a/app/src/protyle/util/compatibility.ts b/app/src/protyle/util/compatibility.ts index 1210fcb07..0d5841104 100644 --- a/app/src/protyle/util/compatibility.ts +++ b/app/src/protyle/util/compatibility.ts @@ -11,7 +11,7 @@ export const openByMobile = (uri: string) => { new URL(uri); window.location.href = uri; } catch (e) { - window.location.href = "http://" + uri; + window.location.href = "https://" + uri; } } else if (isInAndroid()) { window.JSAndroid.openExternal(uri); diff --git a/kernel/job/cron.go b/kernel/job/cron.go index 90db0d75f..5db915460 100644 --- a/kernel/job/cron.go +++ b/kernel/job/cron.go @@ -28,6 +28,7 @@ import ( func StartCron() { go every(100*time.Millisecond, task.ExecTaskJob) + go every(100*time.Millisecond, task.ExecAsyncTaskJob) go every(5*time.Second, task.StatusJob) go every(5*time.Second, model.SyncDataJob) go every(2*time.Hour, model.StatJob) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index c3a334e89..faf8fdcb2 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -3582,7 +3582,7 @@ func updateBoundBlockAvsAttribute(avIDs []string) { } func ReloadAttrView(avID string) { - task.AppendTaskWithDelay(task.ReloadAttributeView, 200*time.Millisecond, pushReloadAttrView, avID) + task.AppendAsyncTaskWithDelay(task.ReloadAttributeView, 200*time.Millisecond, pushReloadAttrView, avID) } diff --git a/kernel/model/bazzar.go b/kernel/model/bazzar.go index 0c9d0dfa2..99660c384 100644 --- a/kernel/model/bazzar.go +++ b/kernel/model/bazzar.go @@ -105,10 +105,7 @@ func BatchUpdateBazaarPackages(frontend string) { } util.ReloadUI() - go func() { - util.WaitForUILoaded() - task.AppendTaskWithDelay(task.PushMsg, 1*time.Second, util.PushMsg, fmt.Sprintf(Conf.language(237), total), 5000) - }() + task.AppendAsyncTaskWithDelay(task.PushMsg, 3*time.Second, util.PushMsg, fmt.Sprintf(Conf.language(237), total), 5000) return } diff --git a/kernel/model/cloud_service.go b/kernel/model/cloud_service.go index c4b6ab2b7..6623931c3 100644 --- a/kernel/model/cloud_service.go +++ b/kernel/model/cloud_service.go @@ -239,7 +239,7 @@ func refreshSubscriptionExpirationRemind() { now := time.Now().UnixMilli() if now >= expired { // 已经过期 if now-expired <= 1000*60*60*24*2 { // 2 天内提醒 https://github.com/siyuan-note/siyuan/issues/7816 - task.AppendTaskWithDelay(task.PushMsg, 30*time.Second, util.PushErrMsg, Conf.Language(128), 0) + task.AppendAsyncTaskWithDelay(task.PushMsg, 30*time.Second, util.PushErrMsg, Conf.Language(128), 0) } return } @@ -250,8 +250,7 @@ func refreshSubscriptionExpirationRemind() { } if 0 < remains && expireDay > remains { - util.WaitForUILoaded() - task.AppendTaskWithDelay(task.PushMsg, 7*time.Second, util.PushErrMsg, fmt.Sprintf(Conf.Language(127), remains), 0) + task.AppendAsyncTaskWithDelay(task.PushMsg, 7*time.Second, util.PushErrMsg, fmt.Sprintf(Conf.Language(127), remains), 0) return } } diff --git a/kernel/model/conf.go b/kernel/model/conf.go index 03c455f35..3c3add304 100644 --- a/kernel/model/conf.go +++ b/kernel/model/conf.go @@ -470,9 +470,9 @@ func InitConf() { go func() { util.WaitForUILoaded() if util.ContainerIOS == util.Container || util.ContainerAndroid == util.Container { - task.AppendTaskWithDelay(task.PushMsg, 2*time.Second, util.PushMsg, Conf.language(245), 15000) + task.AppendAsyncTaskWithDelay(task.PushMsg, 2*time.Second, util.PushMsg, Conf.language(245), 15000) } else { - task.AppendTaskWithDelay(task.PushMsg, 2*time.Second, util.PushMsg, Conf.language(244), 15000) + task.AppendAsyncTaskWithDelay(task.PushMsg, 2*time.Second, util.PushMsg, Conf.language(244), 15000) } }() } diff --git a/kernel/model/index_fix.go b/kernel/model/index_fix.go index 913acf16f..c769b72d1 100644 --- a/kernel/model/index_fix.go +++ b/kernel/model/index_fix.go @@ -256,10 +256,7 @@ func resetDuplicateBlocksOnFileSys() { if needRefreshUI { util.ReloadUI() - go func() { - util.WaitForUILoaded() - task.AppendTaskWithDelay(task.PushMsg, 3*time.Second, util.PushMsg, Conf.Language(190), 5000) - }() + task.AppendAsyncTaskWithDelay(task.PushMsg, 3*time.Second, util.PushMsg, Conf.Language(190), 5000) } } diff --git a/kernel/model/mount.go b/kernel/model/mount.go index e03092735..cc55d4543 100644 --- a/kernel/model/mount.go +++ b/kernel/model/mount.go @@ -219,7 +219,7 @@ func Mount(boxID string) (alreadyMount bool, err error) { Conf.Save() } - task.AppendTaskWithDelay(task.PushMsg, 3*time.Second, util.PushErrMsg, Conf.Language(52), 7000) + task.AppendAsyncTaskWithDelay(task.PushMsg, 3*time.Second, util.PushErrMsg, Conf.Language(52), 7000) go func() { // 每次打开帮助文档时自动检查版本更新并提醒 https://github.com/siyuan-note/siyuan/issues/5057 time.Sleep(time.Second * 10) diff --git a/kernel/model/repository.go b/kernel/model/repository.go index 0980bdb43..bb505a1cf 100644 --- a/kernel/model/repository.go +++ b/kernel/model/repository.go @@ -477,7 +477,7 @@ func ResetRepo() (err error) { Conf.Save() util.PushUpdateMsg(msgId, Conf.Language(145), 3000) - task.AppendTaskWithDelay(task.ReloadUI, 2*time.Second, util.ReloadUI) + task.AppendAsyncTaskWithDelay(task.ReloadUI, 2*time.Second, util.ReloadUI) return } @@ -656,10 +656,7 @@ func checkoutRepo(id string) { task.AppendTask(task.ReloadUI, util.ReloadUIResetScroll) if syncEnabled { - func() { - time.Sleep(5 * time.Second) - util.PushMsg(Conf.Language(134), 0) - }() + task.AppendAsyncTaskWithDelay(task.PushMsg, 7*time.Second, util.PushMsg, Conf.Language(134), 0) } return } diff --git a/kernel/model/search.go b/kernel/model/search.go index 19e152109..ed0687691 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -790,10 +790,7 @@ func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids WaitForWritingFiles() if 0 < len(ids) { - go func() { - time.Sleep(time.Millisecond * 500) - util.ReloadUI() - }() + task.AppendAsyncTaskWithDelay(task.ReloadUI, 500*time.Millisecond, util.ReloadUI) } return } diff --git a/kernel/task/queue.go b/kernel/task/queue.go index 5fc1173c7..db339e5ea 100644 --- a/kernel/task/queue.go +++ b/kernel/task/queue.go @@ -19,6 +19,7 @@ package task import ( "context" "reflect" + "slices" "sync" "time" @@ -37,23 +38,24 @@ type Task struct { Handler reflect.Value Args []interface{} Created time.Time + Async bool // 为 true 说明是异步任务,不会阻塞任务队列,满足 Delay 条件后立即执行 Delay time.Duration Timeout time.Duration } func AppendTask(action string, handler interface{}, args ...interface{}) { - appendTaskWithDelayTimeout(action, 0, 24*time.Hour, handler, args...) + appendTaskWithDelayTimeout(action, false, 0, 24*time.Hour, handler, args...) } -func AppendTaskWithDelay(action string, delay time.Duration, handler interface{}, args ...interface{}) { - appendTaskWithDelayTimeout(action, delay, 24*time.Hour, handler, args...) +func AppendAsyncTaskWithDelay(action string, delay time.Duration, handler interface{}, args ...interface{}) { + appendTaskWithDelayTimeout(action, true, delay, 24*time.Hour, handler, args...) } func AppendTaskWithTimeout(action string, timeout time.Duration, handler interface{}, args ...interface{}) { - appendTaskWithDelayTimeout(action, 0, timeout, handler, args...) + appendTaskWithDelayTimeout(action, false, 0, timeout, handler, args...) } -func appendTaskWithDelayTimeout(action string, delay, timeout time.Duration, handler interface{}, args ...interface{}) { +func appendTaskWithDelayTimeout(action string, async bool, delay, timeout time.Duration, handler interface{}, args ...interface{}) { if util.IsExiting.Load() { //logging.LogWarnf("task queue is paused, action [%s] will be ignored", action) return @@ -64,6 +66,7 @@ func appendTaskWithDelayTimeout(action string, delay, timeout time.Duration, han Handler: reflect.ValueOf(handler), Args: args, Created: time.Now(), + Async: async, Delay: delay, Timeout: timeout, } @@ -175,13 +178,11 @@ func StatusJob() { if nil != actionLangs { if label := actionLangs[task.Action]; nil != label { action = label.(string) + } else { + continue } } - if "" == action { - continue - } - item := map[string]interface{}{"action": action} items = append(items, item) } @@ -220,12 +221,16 @@ func popTask() (ret *Task) { queueLock.Lock() defer queueLock.Unlock() - if 0 == len(taskQueue) { + if 1 > len(taskQueue) { return } for i, task := range taskQueue { - if time.Since(task.Created) > task.Delay { + if time.Since(task.Created) <= task.Delay { + continue + } + + if !task.Async { ret = task taskQueue = append(taskQueue[:i], taskQueue[i+1:]...) return @@ -234,12 +239,69 @@ func popTask() (ret *Task) { return } +func ExecAsyncTaskJob() { + tasks := popAsyncTasks() + if 1 > len(tasks) { + return + } + + if util.IsExiting.Load() { + return + } + + for _, task := range tasks { + go func() { + execTask(task) + }() + } +} + +func popAsyncTasks() (ret []*Task) { + queueLock.Lock() + defer queueLock.Unlock() + + if 1 > len(taskQueue) { + return + } + + var popedIndexes []int + for i, task := range taskQueue { + if !task.Async { + continue + } + + if time.Since(task.Created) <= task.Delay { + continue + } + + if task.Async { + ret = append(ret, task) + popedIndexes = append(popedIndexes, i) + } + } + + if 0 < len(popedIndexes) { + var newQueue []*Task + for i, task := range taskQueue { + if !slices.Contains(popedIndexes, i) { + newQueue = append(newQueue, task) + } + } + taskQueue = newQueue + } + return +} + var ( currentTask *Task currentTaskLock = sync.Mutex{} ) func execTask(task *Task) { + if nil == task { + return + } + defer logging.Recover() args := make([]reflect.Value, len(task.Args)) @@ -251,9 +313,11 @@ func execTask(task *Task) { } } - currentTaskLock.Lock() - currentTask = task - currentTaskLock.Unlock() + if !task.Async { + currentTaskLock.Lock() + currentTask = task + currentTaskLock.Unlock() + } ctx, cancel := context.WithTimeout(context.Background(), task.Timeout) defer cancel() @@ -270,7 +334,9 @@ func execTask(task *Task) { //logging.LogInfof("task [%s] done", task.Action) } - currentTaskLock.Lock() - currentTask = nil - currentTaskLock.Unlock() + if !task.Async { + currentTaskLock.Lock() + currentTask = nil + currentTaskLock.Unlock() + } } diff --git a/kernel/util/runtime.go b/kernel/util/runtime.go index b96bb34ee..ca0d4d7c7 100644 --- a/kernel/util/runtime.go +++ b/kernel/util/runtime.go @@ -45,8 +45,13 @@ var UseSingleLineSave = true var IsUILoaded = false func WaitForUILoaded() { + start := time.Now() for !IsUILoaded { time.Sleep(200 * time.Millisecond) + if time.Since(start) > 30*time.Second { + logging.LogErrorf("wait for ui loaded timeout") + break + } } } diff --git a/kernel/util/websocket.go b/kernel/util/websocket.go index 7813f7976..51d58d7c8 100644 --- a/kernel/util/websocket.go +++ b/kernel/util/websocket.go @@ -153,23 +153,27 @@ func PushTxErr(msg string, code int, data interface{}) { } func PushUpdateMsg(msgId string, msg string, timeout int) { + WaitForUILoaded() BroadcastByType("main", "msg", 0, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout}) return } func PushMsg(msg string, timeout int) (msgId string) { + WaitForUILoaded() msgId = gulu.Rand.String(7) BroadcastByType("main", "msg", 0, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout}) return } func PushErrMsg(msg string, timeout int) (msgId string) { + WaitForUILoaded() msgId = gulu.Rand.String(7) BroadcastByType("main", "msg", -1, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout}) return } func PushStatusBar(msg string) { + WaitForUILoaded() msg += " (" + time.Now().Format("2006-01-02 15:04:05") + ")" BroadcastByType("main", "statusbar", 0, msg, nil) }