2021-01-17 21:46:25 +08:00
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
2018-12-30 11:08:07 +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-12-30 11:08:07 +08:00
2021-05-15 18:13:51 +08:00
// Package gtimer implements timer for interval/delayed jobs running and management.
2019-06-19 09:06:52 +08:00
//
2020-03-06 11:01:03 +08:00
// This package is designed for management for millions of timing jobs. The differences
// between gtimer and gcron are as follows:
// 1. package gcron is implemented based on package gtimer.
2020-01-21 14:46:23 +08:00
// 2. gtimer is designed for high performance and for millions of timing jobs.
2020-03-30 20:31:47 +08:00
// 3. gcron supports configuration pattern grammar like linux crontab, which is more manually
// readable.
2020-03-06 11:01:03 +08:00
// 4. gtimer's benchmark OP is measured in nanoseconds, and gcron's benchmark OP is measured
// in microseconds.
2020-01-21 14:46:23 +08:00
//
2020-03-06 11:01:03 +08:00
// ALSO VERY NOTE the common delay of the timer: https://github.com/golang/go/issues/14410
2019-01-12 22:41:12 +08:00
package gtimer
2019-01-01 19:43:31 +08:00
2019-01-09 12:54:37 +08:00
import (
2021-10-30 15:36:10 +08:00
"context"
2021-11-23 20:26:55 +08:00
"strconv"
2021-05-15 18:13:51 +08:00
"sync"
2019-06-19 09:06:52 +08:00
"time"
2019-07-29 21:01:19 +08:00
2021-11-15 20:49:02 +08:00
"github.com/gogf/gf/v2/container/gtype"
2022-06-16 17:07:25 +08:00
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
2021-11-23 20:26:55 +08:00
"github.com/gogf/gf/v2/internal/command"
2019-01-09 12:54:37 +08:00
)
2018-12-30 11:08:07 +08:00
2021-05-15 18:13:51 +08:00
// Timer is the timer manager, which uses ticks to calculate the timing interval.
type Timer struct {
mu sync . RWMutex
queue * priorityQueue // queue is a priority queue based on heap structure.
status * gtype . Int // status is the current timer status.
ticks * gtype . Int64 // ticks is the proceeded interval number by the timer.
options TimerOptions // timer options is used for timer configuration.
}
// TimerOptions is the configuration object for Timer.
type TimerOptions struct {
Interval time . Duration // Interval is the interval escaped of the timer.
}
2018-12-30 11:08:07 +08:00
const (
2021-06-26 12:08:18 +08:00
StatusReady = 0 // Job or Timer is ready for running.
StatusRunning = 1 // Job or Timer is already running.
StatusStopped = 2 // Job or Timer is stopped.
StatusClosed = - 1 // Job or Timer is closed and waiting to be deleted.
panicExit = "exit" // panicExit is used for custom job exit with panic.
2021-11-23 20:26:55 +08:00
defaultTimerInterval = "100" // defaultTimerInterval is the default timer interval in milliseconds.
2021-06-26 12:08:18 +08:00
commandEnvKeyForInterval = "gf.gtimer.interval" // commandEnvKeyForInterval is the key for command argument or environment configuring default interval duration for timer.
2018-12-30 11:08:07 +08:00
)
var (
2021-11-23 20:26:55 +08:00
defaultInterval = getDefaultInterval ( )
2021-05-15 18:13:51 +08:00
defaultTimer = New ( )
2018-12-30 11:08:07 +08:00
)
2021-11-23 20:26:55 +08:00
func getDefaultInterval ( ) time . Duration {
2022-06-16 17:07:25 +08:00
interval := command . GetOptWithEnv ( commandEnvKeyForInterval , defaultTimerInterval )
n , err := strconv . Atoi ( interval )
2021-11-23 20:26:55 +08:00
if err != nil {
2022-06-16 17:07:25 +08:00
panic ( gerror . WrapCodef (
gcode . CodeInvalidConfiguration , err , ` error converting string "%s" to int number ` ,
interval ,
) )
2021-11-23 20:26:55 +08:00
}
return time . Duration ( n ) * time . Millisecond
}
2021-05-15 18:13:51 +08:00
// DefaultOptions creates and returns a default options object for Timer creation.
func DefaultOptions ( ) TimerOptions {
return TimerOptions {
Interval : defaultInterval ,
}
}
2021-10-21 18:22:47 +08:00
// SetTimeout runs the job once after duration of `delay`.
2020-01-21 14:46:23 +08:00
// It is like the one in javascript.
2021-10-30 15:36:10 +08:00
func SetTimeout ( ctx context . Context , delay time . Duration , job JobFunc ) {
AddOnce ( ctx , delay , job )
2019-01-16 23:23:53 +08:00
}
2021-10-21 18:22:47 +08:00
// SetInterval runs the job every duration of `delay`.
2020-01-21 14:46:23 +08:00
// It is like the one in javascript.
2021-10-30 15:36:10 +08:00
func SetInterval ( ctx context . Context , interval time . Duration , job JobFunc ) {
Add ( ctx , interval , job )
2019-01-16 23:23:53 +08:00
}
2021-10-21 18:22:47 +08:00
// Add adds a timing job to the default timer, which runs in interval of `interval`.
2021-10-30 15:36:10 +08:00
func Add ( ctx context . Context , interval time . Duration , job JobFunc ) * Entry {
return defaultTimer . Add ( ctx , interval , job )
2018-12-30 11:08:07 +08:00
}
2021-05-26 09:55:33 +08:00
// AddEntry adds a timing job to the default timer with detailed parameters.
2020-01-21 14:46:23 +08:00
//
2021-10-21 18:22:47 +08:00
// The parameter `interval` specifies the running interval of the job.
2020-01-21 14:46:23 +08:00
//
2021-10-21 18:22:47 +08:00
// The parameter `singleton` specifies whether the job running in singleton mode.
2020-01-21 14:46:23 +08:00
// There's only one of the same job is allowed running when its a singleton mode job.
//
2021-10-21 18:22:47 +08:00
// The parameter `times` specifies limit for the job running times, which means the job
// exits if its run times exceeds the `times`.
2020-01-21 14:46:23 +08:00
//
2021-10-21 18:22:47 +08:00
// The parameter `status` specifies the job status when it's firstly added to the timer.
2021-10-30 15:36:10 +08:00
func AddEntry ( ctx context . Context , interval time . Duration , job JobFunc , isSingleton bool , times int , status int ) * Entry {
return defaultTimer . AddEntry ( ctx , interval , job , isSingleton , times , status )
2019-01-21 22:09:51 +08:00
}
2020-01-21 14:46:23 +08:00
// AddSingleton is a convenience function for add singleton mode job.
2021-10-30 15:36:10 +08:00
func AddSingleton ( ctx context . Context , interval time . Duration , job JobFunc ) * Entry {
return defaultTimer . AddSingleton ( ctx , interval , job )
2018-12-30 11:08:07 +08:00
}
2020-01-21 14:46:23 +08:00
// AddOnce is a convenience function for adding a job which only runs once and then exits.
2021-10-30 15:36:10 +08:00
func AddOnce ( ctx context . Context , interval time . Duration , job JobFunc ) * Entry {
return defaultTimer . AddOnce ( ctx , interval , job )
2019-01-01 19:43:31 +08:00
}
2020-01-21 14:46:23 +08:00
// AddTimes is a convenience function for adding a job which is limited running times.
2021-10-30 15:36:10 +08:00
func AddTimes ( ctx context . Context , interval time . Duration , times int , job JobFunc ) * Entry {
return defaultTimer . AddTimes ( ctx , interval , times , job )
2018-12-30 11:08:07 +08:00
}
2021-10-21 18:22:47 +08:00
// DelayAdd adds a timing job after delay of `interval` duration.
2020-01-21 14:46:23 +08:00
// Also see Add.
2021-10-30 15:36:10 +08:00
func DelayAdd ( ctx context . Context , delay time . Duration , interval time . Duration , job JobFunc ) {
defaultTimer . DelayAdd ( ctx , delay , interval , job )
2018-12-30 11:08:07 +08:00
}
2021-10-21 18:22:47 +08:00
// DelayAddEntry adds a timing job after delay of `interval` duration.
2021-05-26 09:55:33 +08:00
// Also see AddEntry.
2021-10-30 15:36:10 +08:00
func DelayAddEntry ( ctx context . Context , delay time . Duration , interval time . Duration , job JobFunc , isSingleton bool , times int , status int ) {
defaultTimer . DelayAddEntry ( ctx , delay , interval , job , isSingleton , times , status )
2019-01-21 22:09:51 +08:00
}
2021-10-21 18:22:47 +08:00
// DelayAddSingleton adds a timing job after delay of `interval` duration.
2020-01-21 14:46:23 +08:00
// Also see AddSingleton.
2021-10-30 15:36:10 +08:00
func DelayAddSingleton ( ctx context . Context , delay time . Duration , interval time . Duration , job JobFunc ) {
defaultTimer . DelayAddSingleton ( ctx , delay , interval , job )
2018-12-30 11:08:07 +08:00
}
2021-10-21 18:22:47 +08:00
// DelayAddOnce adds a timing job after delay of `interval` duration.
2020-01-21 14:46:23 +08:00
// Also see AddOnce.
2021-10-30 15:36:10 +08:00
func DelayAddOnce ( ctx context . Context , delay time . Duration , interval time . Duration , job JobFunc ) {
defaultTimer . DelayAddOnce ( ctx , delay , interval , job )
2019-01-01 19:43:31 +08:00
}
2021-10-21 18:22:47 +08:00
// DelayAddTimes adds a timing job after delay of `interval` duration.
2020-01-21 14:46:23 +08:00
// Also see AddTimes.
2021-10-30 15:36:10 +08:00
func DelayAddTimes ( ctx context . Context , delay time . Duration , interval time . Duration , times int , job JobFunc ) {
defaultTimer . DelayAddTimes ( ctx , delay , interval , times , job )
2018-12-30 22:02:46 +08:00
}
2020-03-06 11:01:03 +08:00
// Exit is used in timing job internally, which exits and marks it closed from timer.
// The timing job will be automatically removed from timer later. It uses "panic-recover"
// mechanism internally implementing this feature, which is designed for simplification
// and convenience.
2019-01-02 10:18:00 +08:00
func Exit ( ) {
2020-12-14 13:26:48 +08:00
panic ( panicExit )
2018-12-30 14:53:16 +08:00
}