async triggers for either interval or next due, accept cron

master
bel 2021-07-17 23:14:54 -06:00
parent 9301ddd467
commit 8c7fe2e9ef
3 changed files with 51 additions and 9 deletions

View File

@ -87,37 +87,58 @@ func has(params url.Values, k string) bool {
}
func (a *Ajax) Async() {
var err error
nextDue := time.Now().Add(config.Loop)
c := time.NewTicker(config.Loop)
for range c.C {
for {
select {
case <-c.C:
case <-time.After(time.Until(nextDue)):
}
log.Println("loop tasks")
if err := a.loopTasks(); err != nil {
nextDue, err = a.loopTasks()
if err != nil {
log.Println("failed to loop tasks", err)
}
}
}
func (a *Ajax) loopTasks() error {
func (a *Ajax) loopTasks() (time.Time, error) {
nextDue := time.Now().Add(time.Hour * 240)
lists, err := a.storageListLists()
if err != nil {
return err
return nextDue, err
}
for _, list := range lists {
tasks, err := a.storageListTasks(list.UUID, func(t *task.Task) bool {
return t.Complete
})
if err != nil {
return err
return nextDue, err
}
for _, task := range tasks {
if !task.Complete || task.Loop == 0 || time.Since(task.Completed) < task.Loop {
if !task.Complete {
continue
}
if task.Loop == 0 && task.Cron == "" {
continue
}
nextLoopTrigger := task.Completed.Add(task.Loop)
if task.Loop == 0 {
nextLoopTrigger = task.Cron.Next()
}
if time.Now().Before(nextLoopTrigger) {
if nextLoopTrigger.Before(nextDue) {
nextDue = nextLoopTrigger
}
continue
}
task.Complete = false
task.Completed = time.Time{}
if err := a.storageSetTask(list.UUID, task); err != nil {
return err
return nextDue, err
}
}
}
return nil
return nextDue, nil
}

17
server/ajax/form/cron.go Normal file
View File

@ -0,0 +1,17 @@
package form
import (
"time"
"github.com/robfig/cron/v3"
)
type Cron string
func (c Cron) Next() time.Time {
schedule, err := cron.ParseStandard(string(c))
if err != nil {
return time.Time{}
}
return schedule.Next(time.Now())
}

View File

@ -24,6 +24,7 @@ type Task struct {
Note []string
Due time.Time
Loop time.Duration
Cron form.Cron
Index int
}
@ -45,6 +46,7 @@ func New(r *http.Request) (*Task, error) {
Edited: time.Now(),
Due: form.ToTime(form.Get(r, "duedate")),
Loop: form.ToDuration(form.Get(r, "loop")),
Cron: form.Cron(form.Get(r, "cron")),
}
task.SetNote(form.Get(r, "note"))
return task, task.validate()
@ -75,7 +77,8 @@ func (t *Task) MarshalJSON() ([]byte, error) {
// "dueStr":"",
// "dueInt":33330000,
// "dueTitle":"Due ",
// "loop": "1m"}
// "loop": "1m",
// "cron": "* * * * *"}
// ]}
fullFormat := "02 Jan 2006 03:04 PM"
shortFormat := "02 Jan"
@ -112,6 +115,7 @@ func (t *Task) MarshalJSON() ([]byte, error) {
"dueInt": t.Due.Unix(),
"dueTitle": "Due ",
"loop": t.Loop.String(),
"cron": t.Cron,
}
if t.Due.IsZero() {
for k := range m {