2021-01-17 21:46:25 +08:00
|
|
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
2018-10-25 10:08:08 +08:00
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
2019-02-02 16:18:25 +08:00
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
2018-10-25 10:08:08 +08:00
|
|
|
|
|
|
|
package gcron
|
|
|
|
|
|
|
|
import (
|
2019-06-19 09:06:52 +08:00
|
|
|
"time"
|
2019-07-29 21:01:19 +08:00
|
|
|
|
|
|
|
"github.com/gogf/gf/container/garray"
|
|
|
|
"github.com/gogf/gf/container/gmap"
|
|
|
|
"github.com/gogf/gf/container/gtype"
|
|
|
|
"github.com/gogf/gf/os/glog"
|
|
|
|
"github.com/gogf/gf/os/gtimer"
|
2018-10-25 10:08:08 +08:00
|
|
|
)
|
|
|
|
|
2018-12-30 11:08:07 +08:00
|
|
|
type Cron struct {
|
2021-08-20 11:52:22 +08:00
|
|
|
idGen *gtype.Int64 // Used for unique name generation.
|
|
|
|
status *gtype.Int // Timed task status(0: Not Start; 1: Running; 2: Stopped; -1: Closed)
|
|
|
|
entries *gmap.StrAnyMap // All timed task entries.
|
|
|
|
logger *glog.Logger // Logger, it is nil in default.
|
|
|
|
|
|
|
|
// Logging path(folder).
|
|
|
|
// Deprecated, use logger instead.
|
|
|
|
logPath *gtype.String
|
|
|
|
|
|
|
|
// Logging level.
|
|
|
|
// Deprecated, use logger instead.
|
|
|
|
logLevel *gtype.Int
|
2018-12-30 11:08:07 +08:00
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// New returns a new Cron object with default settings.
|
2018-12-30 11:08:07 +08:00
|
|
|
func New() *Cron {
|
2019-06-19 09:06:52 +08:00
|
|
|
return &Cron{
|
|
|
|
idGen: gtype.NewInt64(),
|
2020-12-14 13:26:48 +08:00
|
|
|
status: gtype.NewInt(StatusRunning),
|
2019-07-23 23:20:27 +08:00
|
|
|
entries: gmap.NewStrAnyMap(true),
|
2019-06-19 09:06:52 +08:00
|
|
|
logPath: gtype.NewString(),
|
|
|
|
logLevel: gtype.NewInt(glog.LEVEL_PROD),
|
|
|
|
}
|
2018-12-30 11:08:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// SetLogger sets the logger for cron.
|
|
|
|
func (c *Cron) SetLogger(logger *glog.Logger) {
|
|
|
|
c.logger = logger
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetLogger returns the logger in the cron.
|
|
|
|
func (c *Cron) GetLogger() *glog.Logger {
|
|
|
|
return c.logger
|
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// SetLogPath sets the logging folder path.
|
2021-08-20 11:52:22 +08:00
|
|
|
// Deprecated, use SetLogger instead.
|
2019-03-19 13:58:18 +08:00
|
|
|
func (c *Cron) SetLogPath(path string) {
|
2019-06-19 09:06:52 +08:00
|
|
|
c.logPath.Set(path)
|
2019-03-19 13:58:18 +08:00
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// GetLogPath return the logging folder path.
|
2021-08-20 11:52:22 +08:00
|
|
|
// Deprecated, use GetLogger instead.
|
2019-03-19 13:58:18 +08:00
|
|
|
func (c *Cron) GetLogPath() string {
|
2019-06-19 09:06:52 +08:00
|
|
|
return c.logPath.Val()
|
2019-03-19 13:58:18 +08:00
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// SetLogLevel sets the logging level.
|
2021-08-20 11:52:22 +08:00
|
|
|
// Deprecated, use SetLogger instead.
|
2019-03-19 13:58:18 +08:00
|
|
|
func (c *Cron) SetLogLevel(level int) {
|
2019-06-19 09:06:52 +08:00
|
|
|
c.logLevel.Set(level)
|
2019-03-19 13:58:18 +08:00
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// GetLogLevel returns the logging level.
|
2021-08-20 11:52:22 +08:00
|
|
|
// Deprecated, use GetLogger instead.
|
2019-03-19 13:58:18 +08:00
|
|
|
func (c *Cron) GetLogLevel() int {
|
2019-06-19 09:06:52 +08:00
|
|
|
return c.logLevel.Val()
|
2019-03-19 13:58:18 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// AddEntry creates and returns a new Entry object.
|
|
|
|
func (c *Cron) AddEntry(pattern string, job func(), times int, singleton bool, name ...string) (*Entry, error) {
|
|
|
|
var (
|
|
|
|
entryName = ""
|
|
|
|
infinite = false
|
|
|
|
)
|
2019-06-19 09:06:52 +08:00
|
|
|
if len(name) > 0 {
|
2021-08-20 11:52:22 +08:00
|
|
|
entryName = name[0]
|
|
|
|
}
|
|
|
|
if times <= 0 {
|
|
|
|
infinite = true
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
2021-08-20 11:52:22 +08:00
|
|
|
return c.doAddEntry(addEntryInput{
|
|
|
|
Name: entryName,
|
|
|
|
Job: job,
|
|
|
|
Times: times,
|
|
|
|
Pattern: pattern,
|
|
|
|
Singleton: singleton,
|
|
|
|
Infinite: infinite,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add adds a timed task.
|
|
|
|
// A unique `name` can be bound with the timed task.
|
|
|
|
// It returns and error if the `name` is already used.
|
|
|
|
func (c *Cron) Add(pattern string, job func(), name ...string) (*Entry, error) {
|
|
|
|
return c.AddEntry(pattern, job, -1, false, name...)
|
2018-12-30 11:08:07 +08:00
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// AddSingleton adds a singleton timed task.
|
|
|
|
// A singleton timed task is that can only be running one single instance at the same time.
|
2021-08-20 11:52:22 +08:00
|
|
|
// A unique `name` can be bound with the timed task.
|
|
|
|
// It returns and error if the `name` is already used.
|
2021-05-26 09:55:33 +08:00
|
|
|
func (c *Cron) AddSingleton(pattern string, job func(), name ...string) (*Entry, error) {
|
2021-08-20 11:52:22 +08:00
|
|
|
return c.AddEntry(pattern, job, -1, true, name...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddTimes adds a timed task which can be run specified times.
|
|
|
|
// A unique `name` can be bound with the timed task.
|
|
|
|
// It returns and error if the `name` is already used.
|
|
|
|
func (c *Cron) AddTimes(pattern string, times int, job func(), name ...string) (*Entry, error) {
|
|
|
|
return c.AddEntry(pattern, job, times, false, name...)
|
2018-12-30 11:08:07 +08:00
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// AddOnce adds a timed task which can be run only once.
|
2021-08-20 11:52:22 +08:00
|
|
|
// A unique `name` can be bound with the timed task.
|
|
|
|
// It returns and error if the `name` is already used.
|
2021-05-26 09:55:33 +08:00
|
|
|
func (c *Cron) AddOnce(pattern string, job func(), name ...string) (*Entry, error) {
|
2021-08-20 11:52:22 +08:00
|
|
|
return c.AddEntry(pattern, job, 1, false, name...)
|
2019-01-16 22:34:22 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// DelayAddEntry adds a timed task after `delay` time.
|
|
|
|
func (c *Cron) DelayAddEntry(delay time.Duration, pattern string, job func(), times int, singleton bool, name ...string) {
|
|
|
|
gtimer.AddOnce(delay, func() {
|
|
|
|
if _, err := c.AddEntry(pattern, job, times, singleton, name...); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
})
|
2018-10-25 10:08:08 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// DelayAdd adds a timed task after `delay` time.
|
2019-06-19 09:06:52 +08:00
|
|
|
func (c *Cron) DelayAdd(delay time.Duration, pattern string, job func(), name ...string) {
|
|
|
|
gtimer.AddOnce(delay, func() {
|
|
|
|
if _, err := c.Add(pattern, job, name...); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
})
|
2018-11-05 10:29:58 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// DelayAddSingleton adds a singleton timed task after `delay` time.
|
2019-06-19 09:06:52 +08:00
|
|
|
func (c *Cron) DelayAddSingleton(delay time.Duration, pattern string, job func(), name ...string) {
|
|
|
|
gtimer.AddOnce(delay, func() {
|
|
|
|
if _, err := c.AddSingleton(pattern, job, name...); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
})
|
2018-10-25 10:08:08 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// DelayAddOnce adds a timed task after `delay` time.
|
2019-05-05 22:57:13 +08:00
|
|
|
// This timed task can be run only once.
|
2019-06-19 09:06:52 +08:00
|
|
|
func (c *Cron) DelayAddOnce(delay time.Duration, pattern string, job func(), name ...string) {
|
|
|
|
gtimer.AddOnce(delay, func() {
|
|
|
|
if _, err := c.AddOnce(pattern, job, name...); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
})
|
2018-12-30 11:08:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// DelayAddTimes adds a timed task after `delay` time.
|
2019-05-05 22:57:13 +08:00
|
|
|
// This timed task can be run specified times.
|
2019-06-19 09:06:52 +08:00
|
|
|
func (c *Cron) DelayAddTimes(delay time.Duration, pattern string, times int, job func(), name ...string) {
|
|
|
|
gtimer.AddOnce(delay, func() {
|
|
|
|
if _, err := c.AddTimes(pattern, times, job, name...); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
})
|
2019-01-16 22:34:22 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// Search returns a scheduled task with the specified `name`.
|
|
|
|
// It returns nil if not found.
|
2021-05-26 09:55:33 +08:00
|
|
|
func (c *Cron) Search(name string) *Entry {
|
2019-06-19 09:06:52 +08:00
|
|
|
if v := c.entries.Get(name); v != nil {
|
2021-05-26 09:55:33 +08:00
|
|
|
return v.(*Entry)
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
return nil
|
2018-10-25 10:08:08 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// Start starts running the specified timed task named `name`.
|
2019-06-19 09:06:52 +08:00
|
|
|
func (c *Cron) Start(name ...string) {
|
|
|
|
if len(name) > 0 {
|
|
|
|
for _, v := range name {
|
|
|
|
if entry := c.Search(v); entry != nil {
|
|
|
|
entry.Start()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2020-12-14 13:26:48 +08:00
|
|
|
c.status.Set(StatusReady)
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
2018-10-25 10:08:08 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// Stop stops running the specified timed task named `name`.
|
2019-06-19 09:06:52 +08:00
|
|
|
func (c *Cron) Stop(name ...string) {
|
|
|
|
if len(name) > 0 {
|
|
|
|
for _, v := range name {
|
|
|
|
if entry := c.Search(v); entry != nil {
|
|
|
|
entry.Stop()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2020-12-14 13:26:48 +08:00
|
|
|
c.status.Set(StatusStopped)
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
2018-10-25 10:08:08 +08:00
|
|
|
}
|
|
|
|
|
2021-08-20 11:52:22 +08:00
|
|
|
// Remove deletes scheduled task which named `name`.
|
2019-04-02 14:37:46 +08:00
|
|
|
func (c *Cron) Remove(name string) {
|
2019-06-19 09:06:52 +08:00
|
|
|
if v := c.entries.Get(name); v != nil {
|
2021-05-26 09:55:33 +08:00
|
|
|
v.(*Entry).Close()
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
2019-04-02 14:37:46 +08:00
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// Close stops and closes current cron.
|
2018-12-30 11:08:07 +08:00
|
|
|
func (c *Cron) Close() {
|
2020-12-14 13:26:48 +08:00
|
|
|
c.status.Set(StatusClosed)
|
2018-12-30 11:08:07 +08:00
|
|
|
}
|
2018-10-25 10:08:08 +08:00
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// Size returns the size of the timed tasks.
|
2018-12-31 17:46:04 +08:00
|
|
|
func (c *Cron) Size() int {
|
2019-06-19 09:06:52 +08:00
|
|
|
return c.entries.Size()
|
2018-12-31 17:46:04 +08:00
|
|
|
}
|
|
|
|
|
2019-05-05 22:57:13 +08:00
|
|
|
// Entries return all timed tasks as slice(order by registered time asc).
|
2021-05-26 09:55:33 +08:00
|
|
|
func (c *Cron) Entries() []*Entry {
|
2019-06-19 09:06:52 +08:00
|
|
|
array := garray.NewSortedArraySize(c.entries.Size(), func(v1, v2 interface{}) int {
|
2021-05-26 09:55:33 +08:00
|
|
|
entry1 := v1.(*Entry)
|
|
|
|
entry2 := v2.(*Entry)
|
2019-06-19 09:06:52 +08:00
|
|
|
if entry1.Time.Nanosecond() > entry2.Time.Nanosecond() {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
return -1
|
|
|
|
}, true)
|
|
|
|
c.entries.RLockFunc(func(m map[string]interface{}) {
|
|
|
|
for _, v := range m {
|
2021-05-26 09:55:33 +08:00
|
|
|
array.Add(v.(*Entry))
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
})
|
2021-05-26 09:55:33 +08:00
|
|
|
entries := make([]*Entry, array.Len())
|
2019-06-19 09:06:52 +08:00
|
|
|
array.RLockFunc(func(array []interface{}) {
|
|
|
|
for k, v := range array {
|
2021-05-26 09:55:33 +08:00
|
|
|
entries[k] = v.(*Entry)
|
2019-06-19 09:06:52 +08:00
|
|
|
}
|
|
|
|
})
|
|
|
|
return entries
|
2018-10-25 10:08:08 +08:00
|
|
|
}
|