Go-cron: A minimal Golang scheduler supporting standard cron expressions
4 months ago
5
Note
This content is translated by LLM. Original text can be found here
Ultra-lightweight Golang scheduler supporting standard cron expressions, custom descriptors, and custom intervals. A minimalist scheduler for Go that makes scheduling effortless.
Originally designed for the scheduling functionality used in threat score decay calculations for pardnchiu/go-ip-sentry.
Built with Go's standard library heap, focusing on core functionality with minimal memory usage and zero learning cost - if you can write cron expressions, you can use this
Supports standard cron expressions, custom descriptors (@hourly, @daily, @weekly, etc.), and custom interval (@every) syntax
Min-heap based task scheduling algorithm with concurrent task execution and management, panic recovery mechanism, and dynamic task addition/removal, ensuring optimal performance in high-volume task scenarios
Click to view
flowchart TD
A[Initialize] --> B[Setup Logger]
B --> C[Initialize Task Heap]
C --> D{Already Running?}
D -->|Yes| D1[No Action]
D -->|No| D2[Start Execution]
D2 --> E[Calculate Initial Task Times]
E --> F[Initialize Min Heap]
F --> G[Start Main Loop]
G --> H{Check Heap Status}
G -->|No Tasks<br>Wait for Events| Q[Listen for Events]
G -->|Has Tasks<br>Set Timer to Next Task| Q
Q --> R{Event Type}
R -->|Timer Expires| R1[Execute Due Tasks]
R -->|Add Task| R2[Add to Heap]
R -->|Remove Task| R3[Remove from Heap]
R -->|Stop Signal| R4[Cleanup and Exit]
R1 --> S[Pop Task from Heap]
S --> T{Check if Enabled}
T -->|Disabled| T0[Skip Task]
T0 --> G
T -->|Enabled| T1{Execute Task Function}
T1 --> T11[Calculate Next Execution Time]
T1 -->|Panic| T10[Recover]
T10 --> T11[Calculate Next Execution Time]
T11 --> U[Re-add to Heap if Recurring]
R2 --> V[Parse Schedule]
V --> W[Create Task Object]
W --> X[Add to Heap]
R3 --> Y[Find Task by ID]
Y --> Z[Mark as Disabled]
Z --> AA[Remove from Heap]
U --> G
X --> G
AA --> G
R4 --> BB[Wait for Running Tasks to Complete]
BB --> CC[Close Channels]
CC --> DD[Scheduler Stopped]
typeConfigstruct {
Log*Log// Logger configurationLocation*time.Location// Timezone setting (default: time.Local)
}
typeLogstruct {
Pathstring// Log file path (default: ./logs/cron.log)Stdoutbool// Output to stdout (default: false)MaxSizeint64// Maximum log file size in bytes (default: 16MB)MaxBackupint// Number of backup files to retain (default: 5)Typestring// Output format: "json" for slog standard, "text" for tree format (default: "text")
}
5-field format: minute hour day month weekday
// Every minutescheduler.Add("* * * * *", task)
// Daily at midnightscheduler.Add("0 0 * * *", task)
// Weekdays at 9 AMscheduler.Add("0 9 * * 1-5", task)
// Every 15 minutesscheduler.Add("*/15 * * * *", task)
// First day of month at 6 AMscheduler.Add("0 6 1 * *", task)
// January 1st at midnightscheduler.Add("@yearly", task)
// First day of month at midnightscheduler.Add("@monthly", task)
// Every Sunday at midnightscheduler.Add("@weekly", task)
// Daily at midnightscheduler.Add("@daily", task)
// Every hour on the hourscheduler.Add("@hourly", task)
// Every 30 secondsscheduler.Add("@every 30s", task)
// Every 5 minutesscheduler.Add("@every 5m", task)
// Every 2 hoursscheduler.Add("@every 2h", task)
// Every 12 hoursscheduler.Add("@every 12h", task)
New - Create new scheduler instance
scheduler, err:=cron.New(config)
Sets up task heap and communication channels
Start - Start scheduler instance
Starts scheduling loop
Stop - Gracefully stop scheduler
ctx:=scheduler.Stop()
<-ctx.Done() // Wait for all tasks to complete
Sends stop signal to main loop
Returns context that completes when all running tasks finish
Ensures graceful shutdown without interrupting tasks