github.com/wangyougui/gf/v2@v2.6.5/os/gtimer/gtimer.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 // Package gtimer implements timer for interval/delayed jobs running and management. 8 // 9 // This package is designed for management for millions of timing jobs. The differences 10 // between gtimer and gcron are as follows: 11 // 1. package gcron is implemented based on package gtimer. 12 // 2. gtimer is designed for high performance and for millions of timing jobs. 13 // 3. gcron supports configuration pattern grammar like linux crontab, which is more manually 14 // readable. 15 // 4. gtimer's benchmark OP is measured in nanoseconds, and gcron's benchmark OP is measured 16 // in microseconds. 17 // 18 // ALSO VERY NOTE the common delay of the timer: https://github.com/golang/go/issues/14410 19 package gtimer 20 21 import ( 22 "context" 23 "strconv" 24 "sync" 25 "time" 26 27 "github.com/wangyougui/gf/v2/container/gtype" 28 "github.com/wangyougui/gf/v2/errors/gcode" 29 "github.com/wangyougui/gf/v2/errors/gerror" 30 "github.com/wangyougui/gf/v2/internal/command" 31 ) 32 33 // Timer is the timer manager, which uses ticks to calculate the timing interval. 34 type Timer struct { 35 mu sync.RWMutex 36 queue *priorityQueue // queue is a priority queue based on heap structure. 37 status *gtype.Int // status is the current timer status. 38 ticks *gtype.Int64 // ticks is the proceeded interval number by the timer. 39 options TimerOptions // timer options is used for timer configuration. 40 } 41 42 // TimerOptions is the configuration object for Timer. 43 type TimerOptions struct { 44 Interval time.Duration // (optional) Interval is the underlying rolling interval tick of the timer. 45 Quick bool // Quick is used for quick timer, which means the timer will not wait for the first interval to be elapsed. 46 } 47 48 // internalPanic is the custom panic for internal usage. 49 type internalPanic string 50 51 const ( 52 StatusReady = 0 // Job or Timer is ready for running. 53 StatusRunning = 1 // Job or Timer is already running. 54 StatusStopped = 2 // Job or Timer is stopped. 55 StatusClosed = -1 // Job or Timer is closed and waiting to be deleted. 56 panicExit internalPanic = "exit" // panicExit is used for custom job exit with panic. 57 defaultTimerInterval = "100" // defaultTimerInterval is the default timer interval in milliseconds. 58 // commandEnvKeyForInterval is the key for command argument or environment configuring default interval duration for timer. 59 commandEnvKeyForInterval = "gf.gtimer.interval" 60 ) 61 62 var ( 63 defaultInterval = getDefaultInterval() 64 defaultTimer = New() 65 ) 66 67 func getDefaultInterval() time.Duration { 68 interval := command.GetOptWithEnv(commandEnvKeyForInterval, defaultTimerInterval) 69 n, err := strconv.Atoi(interval) 70 if err != nil { 71 panic(gerror.WrapCodef( 72 gcode.CodeInvalidConfiguration, err, `error converting string "%s" to int number`, 73 interval, 74 )) 75 } 76 return time.Duration(n) * time.Millisecond 77 } 78 79 // DefaultOptions creates and returns a default options object for Timer creation. 80 func DefaultOptions() TimerOptions { 81 return TimerOptions{ 82 Interval: defaultInterval, 83 } 84 } 85 86 // SetTimeout runs the job once after duration of `delay`. 87 // It is like the one in javascript. 88 func SetTimeout(ctx context.Context, delay time.Duration, job JobFunc) { 89 AddOnce(ctx, delay, job) 90 } 91 92 // SetInterval runs the job every duration of `delay`. 93 // It is like the one in javascript. 94 func SetInterval(ctx context.Context, interval time.Duration, job JobFunc) { 95 Add(ctx, interval, job) 96 } 97 98 // Add adds a timing job to the default timer, which runs in interval of `interval`. 99 func Add(ctx context.Context, interval time.Duration, job JobFunc) *Entry { 100 return defaultTimer.Add(ctx, interval, job) 101 } 102 103 // AddEntry adds a timing job to the default timer with detailed parameters. 104 // 105 // The parameter `interval` specifies the running interval of the job. 106 // 107 // The parameter `singleton` specifies whether the job running in singleton mode. 108 // There's only one of the same job is allowed running when its a singleton mode job. 109 // 110 // The parameter `times` specifies limit for the job running times, which means the job 111 // exits if its run times exceeds the `times`. 112 // 113 // The parameter `status` specifies the job status when it's firstly added to the timer. 114 func AddEntry(ctx context.Context, interval time.Duration, job JobFunc, isSingleton bool, times int, status int) *Entry { 115 return defaultTimer.AddEntry(ctx, interval, job, isSingleton, times, status) 116 } 117 118 // AddSingleton is a convenience function for add singleton mode job. 119 func AddSingleton(ctx context.Context, interval time.Duration, job JobFunc) *Entry { 120 return defaultTimer.AddSingleton(ctx, interval, job) 121 } 122 123 // AddOnce is a convenience function for adding a job which only runs once and then exits. 124 func AddOnce(ctx context.Context, interval time.Duration, job JobFunc) *Entry { 125 return defaultTimer.AddOnce(ctx, interval, job) 126 } 127 128 // AddTimes is a convenience function for adding a job which is limited running times. 129 func AddTimes(ctx context.Context, interval time.Duration, times int, job JobFunc) *Entry { 130 return defaultTimer.AddTimes(ctx, interval, times, job) 131 } 132 133 // DelayAdd adds a timing job after delay of `interval` duration. 134 // Also see Add. 135 func DelayAdd(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) { 136 defaultTimer.DelayAdd(ctx, delay, interval, job) 137 } 138 139 // DelayAddEntry adds a timing job after delay of `interval` duration. 140 // Also see AddEntry. 141 func DelayAddEntry(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc, isSingleton bool, times int, status int) { 142 defaultTimer.DelayAddEntry(ctx, delay, interval, job, isSingleton, times, status) 143 } 144 145 // DelayAddSingleton adds a timing job after delay of `interval` duration. 146 // Also see AddSingleton. 147 func DelayAddSingleton(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) { 148 defaultTimer.DelayAddSingleton(ctx, delay, interval, job) 149 } 150 151 // DelayAddOnce adds a timing job after delay of `interval` duration. 152 // Also see AddOnce. 153 func DelayAddOnce(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) { 154 defaultTimer.DelayAddOnce(ctx, delay, interval, job) 155 } 156 157 // DelayAddTimes adds a timing job after delay of `interval` duration. 158 // Also see AddTimes. 159 func DelayAddTimes(ctx context.Context, delay time.Duration, interval time.Duration, times int, job JobFunc) { 160 defaultTimer.DelayAddTimes(ctx, delay, interval, times, job) 161 }