async triggers for either interval or next due, accept cron
parent
c90cbfc7be
commit
0f8637c9ff
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue