From 9088e49a769d7d8b5d0da3e632a8669ebc133e0a Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Thu, 5 Sep 2024 17:12:54 +0800 Subject: [PATCH 1/3] :art: iOS will display a white screen when clicking on a link without a protocol https://github.com/siyuan-note/siyuan/issues/12038 --- app/src/protyle/util/compatibility.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); From 09eec52a02caf343ca15bbd2158e8da2dcabe0f3 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Thu, 5 Sep 2024 18:07:04 +0800 Subject: [PATCH 2/3] :recycle: Implement some delayed kernel events using task queues https://github.com/siyuan-note/siyuan/issues/12393 --- kernel/model/attribute_view.go | 2 +- kernel/model/bazzar.go | 5 +- kernel/model/cloud_service.go | 5 +- kernel/model/conf.go | 4 +- kernel/model/index_fix.go | 5 +- kernel/model/mount.go | 2 +- kernel/model/repository.go | 7 +-- kernel/task/queue.go | 84 ++++++++++++++++++++++++---------- kernel/util/runtime.go | 5 ++ kernel/util/websocket.go | 4 ++ 10 files changed, 79 insertions(+), 44 deletions(-) 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..0115268f7 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, 3*time.Second, util.PushMsg, Conf.Language(134), 0) } return } diff --git a/kernel/task/queue.go b/kernel/task/queue.go index 5fc1173c7..e8a8cd7b2 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) } @@ -204,8 +205,8 @@ func StatusJob() { } func ExecTaskJob() { - task := popTask() - if nil == task { + syncTask, asyncTasks := popTasks() + if nil == syncTask && 1 > len(asyncTasks) { return } @@ -213,10 +214,18 @@ func ExecTaskJob() { return } - execTask(task) + for _, asyncTask := range asyncTasks { + go func() { + execTask(asyncTask) + }() + } + + if nil != syncTask { + execTask(syncTask) + } } -func popTask() (ret *Task) { +func popTasks() (syncTask *Task, asyncTasks []*Task) { queueLock.Lock() defer queueLock.Unlock() @@ -224,12 +233,31 @@ func popTask() (ret *Task) { return } + var popedIndexes []int for i, task := range taskQueue { - if time.Since(task.Created) > task.Delay { - ret = task - taskQueue = append(taskQueue[:i], taskQueue[i+1:]...) - return + if time.Since(task.Created) <= task.Delay { + continue } + + if task.Async { + asyncTasks = append(asyncTasks, task) + popedIndexes = append(popedIndexes, i) + } else { + if nil == syncTask { + syncTask = 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 } @@ -240,6 +268,10 @@ var ( ) func execTask(task *Task) { + if nil == task { + return + } + defer logging.Recover() args := make([]reflect.Value, len(task.Args)) @@ -251,9 +283,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() @@ -267,10 +301,12 @@ func execTask(task *Task) { case <-ctx.Done(): logging.LogWarnf("task [%s] timeout", task.Action) case <-ch: - //logging.LogInfof("task [%s] done", task.Action) + 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) } From 653a765b1720f8e7dd9465b153b68c733efcbfaa Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Thu, 5 Sep 2024 18:48:35 +0800 Subject: [PATCH 3/3] :recycle: Implement some delayed kernel events using task queues https://github.com/siyuan-note/siyuan/issues/12393 --- kernel/job/cron.go | 1 + kernel/model/repository.go | 2 +- kernel/model/search.go | 5 +-- kernel/task/queue.go | 72 +++++++++++++++++++++++++++----------- 4 files changed, 54 insertions(+), 26 deletions(-) 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/repository.go b/kernel/model/repository.go index 0115268f7..bb505a1cf 100644 --- a/kernel/model/repository.go +++ b/kernel/model/repository.go @@ -656,7 +656,7 @@ func checkoutRepo(id string) { task.AppendTask(task.ReloadUI, util.ReloadUIResetScroll) if syncEnabled { - task.AppendAsyncTaskWithDelay(task.PushMsg, 3*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 e8a8cd7b2..db339e5ea 100644 --- a/kernel/task/queue.go +++ b/kernel/task/queue.go @@ -205,8 +205,8 @@ func StatusJob() { } func ExecTaskJob() { - syncTask, asyncTasks := popTasks() - if nil == syncTask && 1 > len(asyncTasks) { + task := popTask() + if nil == task { return } @@ -214,39 +214,69 @@ func ExecTaskJob() { return } - for _, asyncTask := range asyncTasks { - go func() { - execTask(asyncTask) - }() - } - - if nil != syncTask { - execTask(syncTask) - } + execTask(task) } -func popTasks() (syncTask *Task, asyncTasks []*Task) { +func popTask() (ret *Task) { queueLock.Lock() defer queueLock.Unlock() - if 0 == len(taskQueue) { + if 1 > len(taskQueue) { return } - var popedIndexes []int for i, task := range taskQueue { if time.Since(task.Created) <= task.Delay { continue } + if !task.Async { + ret = task + taskQueue = append(taskQueue[:i], taskQueue[i+1:]...) + return + } + } + 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 { - asyncTasks = append(asyncTasks, task) + ret = append(ret, task) popedIndexes = append(popedIndexes, i) - } else { - if nil == syncTask { - syncTask = task - popedIndexes = append(popedIndexes, i) - } } } @@ -301,7 +331,7 @@ func execTask(task *Task) { case <-ctx.Done(): logging.LogWarnf("task [%s] timeout", task.Action) case <-ch: - logging.LogInfof("task [%s] done", task.Action) + //logging.LogInfof("task [%s] done", task.Action) } if !task.Async {