feat(cron): refactor scheduler to event-driven model and add unit tests#1313
feat(cron): refactor scheduler to event-driven model and add unit tests#1313yinwm merged 3 commits intosipeed:mainfrom
Conversation
nikolasdehor
left a comment
There was a problem hiding this comment.
Good improvement. Replacing the 1s ticker polling with a dynamic time.Timer + wakeChan is a meaningful efficiency gain, especially for PicoClaw's target of low-resource hardware.
Review notes:
-
Timer lifecycle -- the pattern of
NewTimer-> immediateStop-> drain is correct for initializing an "idle" timer. The drain in thewakeChancase (select { case <-timer.C: default: }) properly handles the race between stop and fire. -
Wake channel -- non-blocking sends to
wakeChan(select { case cs.wakeChan <- struct{}{}: default: }) are correct. If a wake is already pending, dropping the duplicate is fine since the loop will recalculate on the next iteration anyway. -
computeNextRun refactor -- the if-chain to switch-case conversion is a clean improvement. Adding the
defaultcase with a log warning for unknown schedule kinds is good defensive programming. -
Test coverage is comprehensive -- CRUD, cron expressions, execution flow with timing, persistence (including invalid JSON), and concurrent access. The concurrent access test with 10 workers x 50 iterations is a good stress test for the mutex logic.
-
Minor concern:
getNextWakeMSis called underRLock, which is correct. ButcheckJobs(called from the timer case) presumably acquires its own lock internally. The flow is: release RLock -> compute delay -> wait on timer -> call checkJobs (which acquires Lock). This is safe since there is no lock held across the wait. -
Nit: the
wakeChannotification inAddJobhappens aftersaveStoreUnsafe, which is good -- the job is persisted before the scheduler is woken. Same inUpdateJob.
LGTM.
Code reviewFound 3 issues:
Lines 435 to 441 in a8b033b
Lines 108 to 120 in a8b033b Suggested fixes: For issue #1: Check if For issue #2: Add For issue #3: Add in if cs.wakeChan != nil {
close(cs.wakeChan)
cs.wakeChan = nil
}🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
In Go, closing a channel (close(ch)) is typically used to inform the receiver that "no more data will be coming." But in the CronService model:
The best way: rely on stopChan to exit the runLoop, and let wakeChan be garbage collected along with the CronService object. |
yinwm
left a comment
There was a problem hiding this comment.
重新审视
经过仔细分析最新提交,我确认之前提出的问题已得到妥善处理:
Issue #1 & #2: 已修复 ✅
wakeChan现在在NewCronService()中初始化EnableJob()和removeJobUnsafe()都添加了notify()调用
Issue #3: 接受作者方案 ✅
你说得对。关闭多发送者的 channel 确实会 panic,你的方案是合理的:
stopChan负责通知退出wakeChan随对象一起被 GC
收回之前的 👎,改为 👍。
一个小建议(非阻塞)
考虑在 AddJob/UpdateJob 等方法入口检查 running 状态,防止 Stop() 后误调用:
if !cs.running {
return nil, errors.New("cron service is not running")
}不过这是 nice-to-have,不影响当前 PR 合并。
LGTM 🎉
yinwm
left a comment
There was a problem hiding this comment.
重新审视
经过仔细分析最新提交,我确认之前提出的问题已得到妥善处理:
Issue #1 & #2: 已修复 ✅
wakeChan现在在NewCronService()中初始化EnableJob()和removeJobUnsafe()都添加了notify()调用
Issue #3: 接受作者方案 ✅
你说得对。关闭多发送者的 channel 确实会 panic,你的方案是合理的:
stopChan负责通知退出wakeChan随对象一起被 GC
收回之前的 👎,改为 👍。
一个小建议(非阻塞)
考虑在 AddJob/UpdateJob 等方法入口检查 running 状态,防止 Stop() 后误调用:
if !cs.running {
return nil, errors.New("cron service is not running")
}不过这是 nice-to-have,不影响当前 PR 合并。
LGTM 🎉
…ts (sipeed#1313) * feat(cron): enhance CronService with wake channel and improve job scheduling logic * fix(cron): update file permission mode to use octal notation in test and fix some lint errors * fix(cron): improve wake channel handling and enhance concurrency in tests
|
@tong3jie Solid refactor on the cron scheduler! Replacing the 1s ticker polling with an event-driven timer is a nice efficiency win, and thanks for adding unit tests to go with it. We have a PicoClaw Dev Group on Discord where contributors share ideas and collaborate. Interested? Send an email to |
…ts (sipeed#1313) * feat(cron): enhance CronService with wake channel and improve job scheduling logic * fix(cron): update file permission mode to use octal notation in test and fix some lint errors * fix(cron): improve wake channel handling and enhance concurrency in tests
📝 Description
feat(cron): refactor scheduler to event-driven model and add unit tests
🗣️ Type of Change
🤖 AI Code Generation
🔗 Related Issue
📚 Technical Context (Skip for Docs)
🧪 Test Environment
📸 Evidence (Optional)
Details
test logs
☑️ Checklist