gf/os/gcron/gcron_cron.go

225 lines
6.6 KiB
Go
Raw Normal View History

2021-01-17 21:46:25 +08:00
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// 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,
// You can obtain one at https://github.com/gogf/gf.
package gcron
import (
"context"
2019-06-19 09:06:52 +08:00
"time"
2019-07-29 21:01:19 +08:00
2021-10-11 21:41:56 +08:00
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/container/gtype"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtimer"
)
// Cron stores all the cron job entries.
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.ILogger // Logger, it is nil in default.
2018-12-30 11:08:07 +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(),
status: gtype.NewInt(StatusRunning),
entries: gmap.NewStrAnyMap(true),
2019-06-19 09:06:52 +08:00
}
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.ILogger) {
2021-08-20 11:52:22 +08:00
c.logger = logger
}
// GetLogger returns the logger in the cron.
func (c *Cron) GetLogger() glog.ILogger {
2021-08-20 11:52:22 +08:00
return c.logger
}
// AddEntry creates and returns a new Entry object.
func (c *Cron) AddEntry(
ctx context.Context, pattern string, job JobFunc, times int, isSingleton bool, name ...string,
) (*Entry, error) {
2021-08-20 11:52:22 +08:00
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
}
return c.doAddEntry(doAddEntryInput{
Name: entryName,
Job: job,
Ctx: ctx,
Times: times,
Pattern: pattern,
IsSingleton: isSingleton,
Infinite: infinite,
2021-08-20 11:52:22 +08:00
})
}
// 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(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) {
return c.AddEntry(ctx, pattern, job, -1, false, name...)
2018-12-30 11:08:07 +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.
func (c *Cron) AddSingleton(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) {
return c.AddEntry(ctx, pattern, job, -1, true, name...)
2021-08-20 11:52:22 +08:00
}
// 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(ctx context.Context, pattern string, times int, job JobFunc, name ...string) (*Entry, error) {
return c.AddEntry(ctx, pattern, job, times, false, name...)
2018-12-30 11:08:07 +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.
func (c *Cron) AddOnce(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) {
return c.AddEntry(ctx, 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(ctx context.Context, delay time.Duration, pattern string, job JobFunc, times int, isSingleton bool, name ...string) {
gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
if _, err := c.AddEntry(ctx, pattern, job, times, isSingleton, name...); err != nil {
2021-08-20 11:52:22 +08:00
panic(err)
}
})
}
2021-08-20 11:52:22 +08:00
// DelayAdd adds a timed task after `delay` time.
func (c *Cron) DelayAdd(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) {
gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
if _, err := c.Add(ctx, pattern, job, name...); err != nil {
2019-06-19 09:06:52 +08:00
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.
func (c *Cron) DelayAddSingleton(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) {
gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
if _, err := c.AddSingleton(ctx, pattern, job, name...); err != nil {
2019-06-19 09:06:52 +08:00
panic(err)
}
})
}
2021-08-20 11:52:22 +08:00
// DelayAddOnce adds a timed task after `delay` time.
// This timed task can be run only once.
func (c *Cron) DelayAddOnce(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) {
gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
if _, err := c.AddOnce(ctx, pattern, job, name...); err != nil {
2019-06-19 09:06:52 +08:00
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.
// This timed task can be run specified times.
func (c *Cron) DelayAddTimes(ctx context.Context, delay time.Duration, pattern string, times int, job JobFunc, name ...string) {
gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
if _, err := c.AddTimes(ctx, pattern, times, job, name...); err != nil {
2019-06-19 09:06:52 +08:00
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.
func (c *Cron) Search(name string) *Entry {
2019-06-19 09:06:52 +08:00
if v := c.entries.Get(name); v != nil {
return v.(*Entry)
2019-06-19 09:06:52 +08:00
}
return nil
}
2021-08-20 11:52:22 +08:00
// Start starts running the specified timed task named `name`.
2021-08-27 20:16:29 +08:00
// If no`name` specified, it starts the entire cron.
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
}
}
2021-08-20 11:52:22 +08:00
// Stop stops running the specified timed task named `name`.
2021-08-27 20:16:29 +08:00
// If no`name` specified, it stops the entire cron.
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
}
}
2021-08-20 11:52:22 +08:00
// Remove deletes scheduled task which named `name`.
func (c *Cron) Remove(name string) {
2019-06-19 09:06:52 +08:00
if v := c.entries.Get(name); v != nil {
v.(*Entry).Close()
2019-06-19 09:06:52 +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
}
// 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
}
// Entries return all timed tasks as slice(order by registered time asc).
func (c *Cron) Entries() []*Entry {
2019-06-19 09:06:52 +08:00
array := garray.NewSortedArraySize(c.entries.Size(), func(v1, v2 interface{}) int {
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 {
array.Add(v.(*Entry))
2019-06-19 09:06:52 +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 {
entries[k] = v.(*Entry)
2019-06-19 09:06:52 +08:00
}
})
return entries
}