♻️ Implement some delayed kernel events using task queues https://github.com/siyuan-note/siyuan/issues/12393

This commit is contained in:
Daniel 2024-09-05 18:07:04 +08:00
parent 9088e49a76
commit 09eec52a02
No known key found for this signature in database
GPG key ID: 86211BA83DF03017
10 changed files with 79 additions and 44 deletions

View file

@ -3582,7 +3582,7 @@ func updateBoundBlockAvsAttribute(avIDs []string) {
} }
func ReloadAttrView(avID string) { func ReloadAttrView(avID string) {
task.AppendTaskWithDelay(task.ReloadAttributeView, 200*time.Millisecond, pushReloadAttrView, avID) task.AppendAsyncTaskWithDelay(task.ReloadAttributeView, 200*time.Millisecond, pushReloadAttrView, avID)
} }

View file

@ -105,10 +105,7 @@ func BatchUpdateBazaarPackages(frontend string) {
} }
util.ReloadUI() util.ReloadUI()
go func() { task.AppendAsyncTaskWithDelay(task.PushMsg, 3*time.Second, util.PushMsg, fmt.Sprintf(Conf.language(237), total), 5000)
util.WaitForUILoaded()
task.AppendTaskWithDelay(task.PushMsg, 1*time.Second, util.PushMsg, fmt.Sprintf(Conf.language(237), total), 5000)
}()
return return
} }

View file

@ -239,7 +239,7 @@ func refreshSubscriptionExpirationRemind() {
now := time.Now().UnixMilli() now := time.Now().UnixMilli()
if now >= expired { // 已经过期 if now >= expired { // 已经过期
if now-expired <= 1000*60*60*24*2 { // 2 天内提醒 https://github.com/siyuan-note/siyuan/issues/7816 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 return
} }
@ -250,8 +250,7 @@ func refreshSubscriptionExpirationRemind() {
} }
if 0 < remains && expireDay > remains { if 0 < remains && expireDay > remains {
util.WaitForUILoaded() task.AppendAsyncTaskWithDelay(task.PushMsg, 7*time.Second, util.PushErrMsg, fmt.Sprintf(Conf.Language(127), remains), 0)
task.AppendTaskWithDelay(task.PushMsg, 7*time.Second, util.PushErrMsg, fmt.Sprintf(Conf.Language(127), remains), 0)
return return
} }
} }

View file

@ -470,9 +470,9 @@ func InitConf() {
go func() { go func() {
util.WaitForUILoaded() util.WaitForUILoaded()
if util.ContainerIOS == util.Container || util.ContainerAndroid == util.Container { 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 { } 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)
} }
}() }()
} }

View file

@ -256,10 +256,7 @@ func resetDuplicateBlocksOnFileSys() {
if needRefreshUI { if needRefreshUI {
util.ReloadUI() util.ReloadUI()
go func() { task.AppendAsyncTaskWithDelay(task.PushMsg, 3*time.Second, util.PushMsg, Conf.Language(190), 5000)
util.WaitForUILoaded()
task.AppendTaskWithDelay(task.PushMsg, 3*time.Second, util.PushMsg, Conf.Language(190), 5000)
}()
} }
} }

View file

@ -219,7 +219,7 @@ func Mount(boxID string) (alreadyMount bool, err error) {
Conf.Save() 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() { go func() {
// 每次打开帮助文档时自动检查版本更新并提醒 https://github.com/siyuan-note/siyuan/issues/5057 // 每次打开帮助文档时自动检查版本更新并提醒 https://github.com/siyuan-note/siyuan/issues/5057
time.Sleep(time.Second * 10) time.Sleep(time.Second * 10)

View file

@ -477,7 +477,7 @@ func ResetRepo() (err error) {
Conf.Save() Conf.Save()
util.PushUpdateMsg(msgId, Conf.Language(145), 3000) 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 return
} }
@ -656,10 +656,7 @@ func checkoutRepo(id string) {
task.AppendTask(task.ReloadUI, util.ReloadUIResetScroll) task.AppendTask(task.ReloadUI, util.ReloadUIResetScroll)
if syncEnabled { if syncEnabled {
func() { task.AppendAsyncTaskWithDelay(task.PushMsg, 3*time.Second, util.PushMsg, Conf.Language(134), 0)
time.Sleep(5 * time.Second)
util.PushMsg(Conf.Language(134), 0)
}()
} }
return return
} }

View file

@ -19,6 +19,7 @@ package task
import ( import (
"context" "context"
"reflect" "reflect"
"slices"
"sync" "sync"
"time" "time"
@ -37,23 +38,24 @@ type Task struct {
Handler reflect.Value Handler reflect.Value
Args []interface{} Args []interface{}
Created time.Time Created time.Time
Async bool // 为 true 说明是异步任务,不会阻塞任务队列,满足 Delay 条件后立即执行
Delay time.Duration Delay time.Duration
Timeout time.Duration Timeout time.Duration
} }
func AppendTask(action string, handler interface{}, args ...interface{}) { 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{}) { func AppendAsyncTaskWithDelay(action string, delay time.Duration, handler interface{}, args ...interface{}) {
appendTaskWithDelayTimeout(action, delay, 24*time.Hour, handler, args...) appendTaskWithDelayTimeout(action, true, delay, 24*time.Hour, handler, args...)
} }
func AppendTaskWithTimeout(action string, timeout time.Duration, handler interface{}, args ...interface{}) { 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() { if util.IsExiting.Load() {
//logging.LogWarnf("task queue is paused, action [%s] will be ignored", action) //logging.LogWarnf("task queue is paused, action [%s] will be ignored", action)
return return
@ -64,6 +66,7 @@ func appendTaskWithDelayTimeout(action string, delay, timeout time.Duration, han
Handler: reflect.ValueOf(handler), Handler: reflect.ValueOf(handler),
Args: args, Args: args,
Created: time.Now(), Created: time.Now(),
Async: async,
Delay: delay, Delay: delay,
Timeout: timeout, Timeout: timeout,
} }
@ -175,13 +178,11 @@ func StatusJob() {
if nil != actionLangs { if nil != actionLangs {
if label := actionLangs[task.Action]; nil != label { if label := actionLangs[task.Action]; nil != label {
action = label.(string) action = label.(string)
} else {
continue
} }
} }
if "" == action {
continue
}
item := map[string]interface{}{"action": action} item := map[string]interface{}{"action": action}
items = append(items, item) items = append(items, item)
} }
@ -204,8 +205,8 @@ func StatusJob() {
} }
func ExecTaskJob() { func ExecTaskJob() {
task := popTask() syncTask, asyncTasks := popTasks()
if nil == task { if nil == syncTask && 1 > len(asyncTasks) {
return return
} }
@ -213,10 +214,18 @@ func ExecTaskJob() {
return 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() queueLock.Lock()
defer queueLock.Unlock() defer queueLock.Unlock()
@ -224,12 +233,31 @@ func popTask() (ret *Task) {
return return
} }
var popedIndexes []int
for i, task := range taskQueue { for i, task := range taskQueue {
if time.Since(task.Created) > task.Delay { if time.Since(task.Created) <= task.Delay {
ret = task continue
taskQueue = append(taskQueue[:i], taskQueue[i+1:]...)
return
} }
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 return
} }
@ -240,6 +268,10 @@ var (
) )
func execTask(task *Task) { func execTask(task *Task) {
if nil == task {
return
}
defer logging.Recover() defer logging.Recover()
args := make([]reflect.Value, len(task.Args)) args := make([]reflect.Value, len(task.Args))
@ -251,9 +283,11 @@ func execTask(task *Task) {
} }
} }
currentTaskLock.Lock() if !task.Async {
currentTask = task currentTaskLock.Lock()
currentTaskLock.Unlock() currentTask = task
currentTaskLock.Unlock()
}
ctx, cancel := context.WithTimeout(context.Background(), task.Timeout) ctx, cancel := context.WithTimeout(context.Background(), task.Timeout)
defer cancel() defer cancel()
@ -267,10 +301,12 @@ func execTask(task *Task) {
case <-ctx.Done(): case <-ctx.Done():
logging.LogWarnf("task [%s] timeout", task.Action) logging.LogWarnf("task [%s] timeout", task.Action)
case <-ch: case <-ch:
//logging.LogInfof("task [%s] done", task.Action) logging.LogInfof("task [%s] done", task.Action)
} }
currentTaskLock.Lock() if !task.Async {
currentTask = nil currentTaskLock.Lock()
currentTaskLock.Unlock() currentTask = nil
currentTaskLock.Unlock()
}
} }

View file

@ -45,8 +45,13 @@ var UseSingleLineSave = true
var IsUILoaded = false var IsUILoaded = false
func WaitForUILoaded() { func WaitForUILoaded() {
start := time.Now()
for !IsUILoaded { for !IsUILoaded {
time.Sleep(200 * time.Millisecond) time.Sleep(200 * time.Millisecond)
if time.Since(start) > 30*time.Second {
logging.LogErrorf("wait for ui loaded timeout")
break
}
} }
} }

View file

@ -153,23 +153,27 @@ func PushTxErr(msg string, code int, data interface{}) {
} }
func PushUpdateMsg(msgId string, msg string, timeout int) { func PushUpdateMsg(msgId string, msg string, timeout int) {
WaitForUILoaded()
BroadcastByType("main", "msg", 0, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout}) BroadcastByType("main", "msg", 0, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout})
return return
} }
func PushMsg(msg string, timeout int) (msgId string) { func PushMsg(msg string, timeout int) (msgId string) {
WaitForUILoaded()
msgId = gulu.Rand.String(7) msgId = gulu.Rand.String(7)
BroadcastByType("main", "msg", 0, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout}) BroadcastByType("main", "msg", 0, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout})
return return
} }
func PushErrMsg(msg string, timeout int) (msgId string) { func PushErrMsg(msg string, timeout int) (msgId string) {
WaitForUILoaded()
msgId = gulu.Rand.String(7) msgId = gulu.Rand.String(7)
BroadcastByType("main", "msg", -1, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout}) BroadcastByType("main", "msg", -1, msg, map[string]interface{}{"id": msgId, "closeTimeout": timeout})
return return
} }
func PushStatusBar(msg string) { func PushStatusBar(msg string) {
WaitForUILoaded()
msg += " (" + time.Now().Format("2006-01-02 15:04:05") + ")" msg += " (" + time.Now().Format("2006-01-02 15:04:05") + ")"
BroadcastByType("main", "statusbar", 0, msg, nil) BroadcastByType("main", "statusbar", 0, msg, nil)
} }