Scheduler (Cron Jobs)
core.Scheduler wraps gocron v2. Each run gets a fresh ICronjobContext (a full IContext in ModeCron), a panic is turned into a logged error (never crashes the scheduler), and failures are logged.
A tick queues a run rather than calling the handler directly, so every scheduled job also gets a status record, retries, concurrency limits and cancellation. The API on this page is unchanged — see jobs.md for manual triggers, parameters, queueing, status and logs.
Setup
go
sc, err := core.NewScheduler(app)
if err != nil { panic(err) }
sc.AddByCron("nightly-report", "0 2 * * *", SendReport) // 5/6-field cron
sc.AddByDuration("heartbeat", 30*time.Second, Heartbeat)
sc.Start() // non-blocking
defer sc.Stop() // graceful shutdownA job
A job is a func(c core.ICronjobContext) error — it has every capability:
go
func SendReport(c core.ICronjobContext) error {
c.Log().Info("building report", "job", c.JobName())
users, err := repository.New[User](c).Where("active = ?", true).FindAll()
if err != nil {
return err // logged automatically
}
// ... use c.DB(), c.Cache(), c.Requester(), c.MQ() as usual
return nil
}Behaviour
- Fresh context per run —
ModeCron, independent of any request. - Panic safety — a panicking job returns an error (with stack) instead of taking down the scheduler.
- Errors logged — a non-nil return is logged with the job name.
- Invalid cron expressions are rejected by
AddByCronat registration time.
API
go
func NewScheduler(app *core.App) (*core.Scheduler, IError)
func (s *Scheduler) AddByCron(name, cronExpr string, fn JobFunc) IError
func (s *Scheduler) AddByDuration(name string, d time.Duration, fn JobFunc) IError
func (s *Scheduler) Start()
func (s *Scheduler) Stop() IError
type ICronjobContext interface {
core.IContext
JobName() string
}