Golang: Реализация задачи cron/выполнения в определенное время
Я искал примеры того, как реализовать функцию, которая позволяет выполнять задачи в определенное время в Go, но я ничего не мог найти.
Я сам реализовал его, и я делюсь им в ответах, поэтому другие люди могут иметь ссылку для своей собственной реализации.
Ответы
Ответ 1
Это общая реализация, которая позволяет установить:
- период интервала
- час, чтобы отметить
- минут на галочку
- второй пометить
Пример работы можно найти здесь: http://play.golang.org/p/xEtiMDZhXt
import (
"fmt"
"time"
)
const INTERVAL_PERIOD time.Duration = 24 * time.Hour
const HOUR_TO_TICK int = 23
const MINUTE_TO_TICK int = 00
const SECOND_TO_TICK int = 03
func runningRoutine() {
ticker := updateTicker()
for {
<-ticker.C
fmt.Println(time.Now(), "- just ticked")
ticker = updateTicker()
}
}
func updateTicker() *time.Ticker {
nextTick := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), HOUR_TO_TICK, MINUTE_TO_TICK, SECOND_TO_TICK, 0, time.Local)
if !nextTick.After(time.Now()) {
nextTick = nextTick.Add(INTERVAL_PERIOD)
}
fmt.Println(nextTick, "- next tick")
diff := nextTick.Sub(time.Now())
return time.NewTicker(diff)
}
Ответ 2
ответ, предоставленный @Daniele B, недостаточно хорош, как говорит @Caleb, что реализация утечки памяти, потому что каждый раз, когда мы создаем новый тикер, старый никогда не будет выпущен.
поэтому я завершаю time.timer
и каждый раз перезагружаю его, пример:
package main
import (
"fmt"
"time"
)
const INTERVAL_PERIOD time.Duration = 24 * time.Hour
const HOUR_TO_TICK int = 23
const MINUTE_TO_TICK int = 21
const SECOND_TO_TICK int = 03
type jobTicker struct {
t *time.Timer
}
func getNextTickDuration() time.Duration {
now := time.Now()
nextTick := time.Date(now.Year(), now.Month(), now.Day(), HOUR_TO_TICK, MINUTE_TO_TICK, SECOND_TO_TICK, 0, time.Local)
if nextTick.Before(now) {
nextTick = nextTick.Add(INTERVAL_PERIOD)
}
return nextTick.Sub(time.Now())
}
func NewJobTicker() jobTicker {
fmt.Println("new tick here")
return jobTicker{time.NewTimer(getNextTickDuration())}
}
func (jt jobTicker) updateJobTicker() {
fmt.Println("next tick here")
jt.t.Reset(getNextTickDuration())
}
func main() {
jt := NewJobTicker()
for {
<-jt.t.C
fmt.Println(time.Now(), "- just ticked")
jt.updateJobTicker()
}
}
Ответ 3
В случае, если кто-то займется этим вопросом, ища быстрое решение. Я нашел аккуратную библиотеку, которая упрощает планирование заданий.
Ссылка: https://github.com/jasonlvhit/gocron
API довольно прост:
import (
"fmt"
"github.com/jasonlvhit/gocron"
)
func task() {
fmt.Println("Task is being performed.")
}
func main() {
s := gocron.NewScheduler()
s.Every(2).Hours().Do(task)
<- s.Start()
}
Ответ 4
Я создал пакет, который фактически поддерживает синтаксис crontab, если вы знакомы с ним, например:
ctab := crontab.New()
ctab.AddJob("*/5 * * * *", myFunc)
ctab.AddJob("0 0 * * *", myFunc2)
Ссылка на пакет: https://github.com/mileusna/crontab
Ответ 5
Код очень запутан, чтобы читать, немного сложно понять, какие переменные времени и которые являются переменными тикера.
Я думаю, что это более или менее правильное дело, выяснить, как долго между этим и следующим "тиком" и спать до этого тика.
Может быть более поучительно использовать
func AfterFunc
func AfterFunc(d Duration, f func()) *Timer
AfterFunc waits for the duration to elapse and then calls f in its own goroutine. It returns a Timer that can be used to cancel the call using its Stop method.
Это приблизилось бы к тому, что вы пытаетесь дублировать и чувствуете себя более похожими на меня.