Add support for schedules (#137)
Reviewed-on: #137
This commit was merged in pull request #137.
This commit is contained in:
104
backend/db.go
104
backend/db.go
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/adhocore/gronx"
|
||||
"log"
|
||||
"math"
|
||||
"time"
|
||||
@@ -313,10 +314,20 @@ func (db *Db) CreateTask(task *CreateTaskRequest) (int, error) {
|
||||
}
|
||||
defer tx.MustRollback()
|
||||
|
||||
var nextRun *int64
|
||||
if task.Schedule != nil {
|
||||
nextRunTime, err := gronx.NextTick(*task.Schedule, false)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to calculate next run: %w", err)
|
||||
}
|
||||
nextRunTimeAsInt := nextRunTime.Unix()
|
||||
nextRun = &nextRunTimeAsInt
|
||||
}
|
||||
|
||||
// Insert the new task
|
||||
reward := int(math.Round(task.Reward * 100.0))
|
||||
err = tx.Query("insert into tasks (name, reward, assigned) values (?, ?, ?)").
|
||||
Bind(task.Name, reward, task.Assigned).
|
||||
err = tx.Query("insert into tasks (name, reward, assigned, schedule, next_run) values (?, ?, ?, ?, ?)").
|
||||
Bind(task.Name, reward, task.Assigned, task.Schedule, nextRun).
|
||||
Exec()
|
||||
|
||||
if err != nil {
|
||||
@@ -340,13 +351,17 @@ func (db *Db) CreateTask(task *CreateTaskRequest) (int, error) {
|
||||
}
|
||||
|
||||
func (db *Db) GetTasks() ([]Task, error) {
|
||||
tasks := make([]Task, 0)
|
||||
var err error
|
||||
err := db.UpdateScheduledTasks()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update scheduled tasks: %w", err)
|
||||
}
|
||||
|
||||
for row := range db.db.Query("select id, name, reward, assigned from tasks").Range(&err) {
|
||||
tasks := make([]Task, 0)
|
||||
|
||||
for row := range db.db.Query("select id, name, reward, assigned, schedule from tasks where completed is null").Range(&err) {
|
||||
task := Task{}
|
||||
var reward int64
|
||||
err = row.Scan(&task.ID, &task.Name, &reward, &task.Assigned)
|
||||
err = row.Scan(&task.ID, &task.Name, &reward, &task.Assigned, &task.Schedule)
|
||||
task.Reward = float64(reward) / 100.0
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -362,16 +377,78 @@ func (db *Db) GetTasks() ([]Task, error) {
|
||||
func (db *Db) GetTask(id int) (Task, error) {
|
||||
task := Task{}
|
||||
|
||||
var reward int64
|
||||
err := db.db.Query("select id, name, reward, assigned from tasks where id = ?").
|
||||
Bind(id).ScanSingle(&task.ID, &task.Name, &reward, &task.Assigned)
|
||||
task.Reward = float64(reward) / 100.0
|
||||
err := db.UpdateScheduledTasks()
|
||||
if err != nil {
|
||||
return Task{}, err
|
||||
return Task{}, fmt.Errorf("failed to update scheduled tasks: %w", err)
|
||||
}
|
||||
|
||||
var reward int64
|
||||
err = db.db.Query("select id, name, reward, assigned, schedule from tasks where id = ? and completed is null").
|
||||
Bind(id).ScanSingle(&task.ID, &task.Name, &reward, &task.Assigned, &task.Schedule)
|
||||
if err != nil {
|
||||
return task, err
|
||||
}
|
||||
task.Reward = float64(reward) / 100.0
|
||||
return task, nil
|
||||
}
|
||||
|
||||
func (db *Db) UpdateScheduledTasks() error {
|
||||
type ScheduledTask struct {
|
||||
ID int
|
||||
Schedule string
|
||||
Expires int64
|
||||
}
|
||||
tasks := make([]ScheduledTask, 0)
|
||||
var err error
|
||||
|
||||
for row := range db.db.Query("select id, schedule, next_run from tasks where schedule is not null").Range(&err) {
|
||||
task := ScheduledTask{}
|
||||
err := row.Scan(&task.ID, &task.Schedule, &task.Expires)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix() >= task.Expires {
|
||||
tasks = append(tasks, task)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch scheduled tasks: %w", err)
|
||||
}
|
||||
|
||||
tx, err := db.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.MustRollback()
|
||||
|
||||
for _, task := range tasks {
|
||||
nextRun, err := gronx.NextTickAfter(task.Schedule, time.Now(), false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to calculate next run for task %d: %w", task.ID, err)
|
||||
}
|
||||
|
||||
err = tx.Query("insert into tasks (name, reward, assigned, schedule, next_run) select name, reward, assigned, schedule, ? from tasks where id = ?").
|
||||
Bind(nextRun.Unix(), task.ID).
|
||||
Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Query("update tasks set schedule = null where id = ?").Bind(task.ID).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx.Query("select last_insert_rowid()").MustScanSingle(&task.ID)
|
||||
log.Printf("Task %d scheduled for %s", task.ID, nextRun)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (db *Db) DeleteTask(id int) error {
|
||||
tx, err := db.db.Begin()
|
||||
if err != nil {
|
||||
@@ -453,7 +530,10 @@ func (db *Db) CompleteTask(taskId int) error {
|
||||
}
|
||||
|
||||
// Remove the task
|
||||
err = tx.Query("delete from tasks where id = ?").Bind(taskId).Exec()
|
||||
err = tx.Query("update tasks set completed=? where id = ?").Bind(time.Now().Unix(), taskId).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user