This is a library to handle scheduled tasks. The task list is stored in the database (GORM).
- Import the library.
import "github.com/rosberry/go-scheduler"
- Use
gorm
ORM library to work with the database in the scheduler. You make use structurescheduler.Task
for create migration.
tx := db.Begin()
tx.Migrator().AutoMigrate(&scheduler.Task{})
- Initialize the scheduler with 3 arguments:
gorm db
,taskFuncMap
,sleepDuration
.
gorm db
: instance*gorm.DB
in gorm library.
taskFuncMap
: Before adding argument we should create schedule function(s) and add them to the special mapscheduler.TaskFuncsMap
. Each function must return 2 parameters. The first is the status after the completion of the task. Possible options:TaskStatusDone
,TaskStatusWait
,TaskStatusDeferred
. The second is how long it will take to call this task again. The passed types can be:time.Duration
,time.Time
ornil
. If the time was not transmitted (nil was used), then we will use the static values stored in the database for this task. More on this later.
sleepDuration
: time interval between checking tasks. By default it is 30 seconds and can be set up no less than this value.
printFunc := func(args scheduler.FuncArgs) (scheduler.TaskStatus, interface{}) {
log.Print("Hello scheduler!")
nextStart := time.Now().Add(time.Minute * 1)
return scheduler.TaskStatusWait, nextStart
}
sch := scheduler.New(
db, // gorm db
&scheduler.TaskFuncsMap{
"print": printFunc,
},
time.Minute * 5, // sleep duration
)
go sch.Run()
You can add a static interval for the execution of tasks. If a time is specified for a task, then it will be singleton.
taskPlan := scheduler.TaskPlan{
"print": 5, // 5 minutes
}
sch.Configure(taskPlan)
// ...
go sch.Run()
You can add a dynamic tasks adding code after running scheduler.
go sch.Run()
// ...
sch.Add(
"upd_print", // alias
"upd_print_1", // current name
scheduler.FuncArgs{ "name": "Ivan" }, // arguments
time.Now().Add(time.Second*10), // runAt
5, // interval in minutes
)
You can simple inintialize scheduler with singleton and arguments:
sch, err := scheduler.NewWithConfig(scheduler.Config{
Db: db,
Jobs: scheduler.TaskSettings{
testObj.Alias: {
Interval: 5, // 5 minutes
Func: printFunc, // job func
Args: scheduler.FuncArgs{
"name": "print",
},
},
},
Sleep: scheduler.MinimalSleepDuration,
})
// ...
go sch.Run()
You can create your task model for scheduler migration. To do this, make sure your structure meets the minimum requirements of the basic scheduler structure:
type Task struct {
ID uint `gorm:"primary_key"`
Alias string
Name string
Arguments string
Singleton bool
Status TaskStatus
Schedule uint
ScheduledAt time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
package main
import (
"fmt"
"log"
"time"
scheduler "github.com/rosberry/go-schedule"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
const (
sleepDuration = time.Minute
updPrintScheduleTimeout = 5
)
func main() {
// Connect to DB
connString := "host=localhost port=5432 user=postgres dbname=clapper password=123 sslmode=disable"
db, err := gorm.Open(postgres.Open(connString), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
// Create FuncsMap and add our TaskFunc's
taskFuncsMap := scheduler.TaskFuncsMap{
"upd_print": PrintJobSingleton,
"upd_printName": PrintWithArgs,
}
// Init TaskPlan for Singleton functions
taskPlan := scheduler.TaskPlan{
"upd_print": updPrintScheduleTimeout,
}
// Init scheduler
sch := scheduler.New(db, &taskFuncsMap, sleepDuration) // gorm db in first func argument
// Add to DB and configure singleton tasks
sch.Configure(taskPlan)
// Run scheduler
go sch.Run()
for i := 0; i < 3; i++ {
sch.Add(
"upd_printName",
fmt.Sprintf("upd_printName #%v", i),
scheduler.FuncArgs{"name": fmt.Sprintf("Ivan %v", i)},
time.Now().Add(time.Second*10),
0,
)
time.Sleep(time.Second * 3)
}
// Stub
time.Sleep(time.Hour)
log.Println("exit")
}
// Create schedule TaskFunc's
// PrintJobSingleton ...
func PrintJobSingleton(args scheduler.FuncArgs) (status scheduler.TaskStatus, when interface{}) {
log.Println("PrintJobSingleton:", time.Now())
return scheduler.TaskStatusWait, time.Now().Add(time.Minute * 1)
}
// PrintWithArgs ...
func PrintWithArgs(args scheduler.FuncArgs) (status scheduler.TaskStatus, when interface{}) {
if name, ok := args["name"]; ok {
log.Println("PrintWithArgs:", time.Now(), name)
return scheduler.TaskStatusWait, time.Now().Add(time.Minute * 1)
}
log.Print("Not found name arg in func args")
return scheduler.TaskStatusDeferred, time.Now().Add(time.Minute * 1)
}
- Singleton - unique task, can be only one task with alias in DB.
- Not singleton - dynamic task, that can be created while the program is running, supports arguments, there can be several tasks in the database with one alias.
- Scheduled tasks
- Once tasks
- Concurency
- Transactions
- Configure tasks
- ...
This project is owned and maintained by Rosberry. We build mobile apps for users worldwide 🌏.
Check out our open source projects, read our blog or give us a high-five on 🐦 @rosberryapps.
This project is available under the MIT license. See the LICENSE file for more info.