github.com/wangyougui/gf/v2@v2.6.5/os/gcron/gcron_cron.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 gcron 8 9 import ( 10 "context" 11 "time" 12 13 "github.com/wangyougui/gf/v2/container/garray" 14 "github.com/wangyougui/gf/v2/container/gmap" 15 "github.com/wangyougui/gf/v2/container/gtype" 16 "github.com/wangyougui/gf/v2/os/glog" 17 "github.com/wangyougui/gf/v2/os/gtimer" 18 ) 19 20 // Cron stores all the cron job entries. 21 type Cron struct { 22 idGen *gtype.Int64 // Used for unique name generation. 23 status *gtype.Int // Timed task status(0: Not Start; 1: Running; 2: Stopped; -1: Closed) 24 entries *gmap.StrAnyMap // All timed task entries. 25 logger glog.ILogger // Logger, it is nil in default. 26 } 27 28 // New returns a new Cron object with default settings. 29 func New() *Cron { 30 return &Cron{ 31 idGen: gtype.NewInt64(), 32 status: gtype.NewInt(StatusRunning), 33 entries: gmap.NewStrAnyMap(true), 34 } 35 } 36 37 // SetLogger sets the logger for cron. 38 func (c *Cron) SetLogger(logger glog.ILogger) { 39 c.logger = logger 40 } 41 42 // GetLogger returns the logger in the cron. 43 func (c *Cron) GetLogger() glog.ILogger { 44 return c.logger 45 } 46 47 // AddEntry creates and returns a new Entry object. 48 func (c *Cron) AddEntry( 49 ctx context.Context, pattern string, job JobFunc, times int, isSingleton bool, name ...string, 50 ) (*Entry, error) { 51 var ( 52 entryName = "" 53 infinite = false 54 ) 55 if len(name) > 0 { 56 entryName = name[0] 57 } 58 if times <= 0 { 59 infinite = true 60 } 61 return c.doAddEntry(doAddEntryInput{ 62 Name: entryName, 63 Job: job, 64 Ctx: ctx, 65 Times: times, 66 Pattern: pattern, 67 IsSingleton: isSingleton, 68 Infinite: infinite, 69 }) 70 } 71 72 // Add adds a timed task. 73 // A unique `name` can be bound with the timed task. 74 // It returns and error if the `name` is already used. 75 func (c *Cron) Add(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) { 76 return c.AddEntry(ctx, pattern, job, -1, false, name...) 77 } 78 79 // AddSingleton adds a singleton timed task. 80 // A singleton timed task is that can only be running one single instance at the same time. 81 // A unique `name` can be bound with the timed task. 82 // It returns and error if the `name` is already used. 83 func (c *Cron) AddSingleton(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) { 84 return c.AddEntry(ctx, pattern, job, -1, true, name...) 85 } 86 87 // AddTimes adds a timed task which can be run specified times. 88 // A unique `name` can be bound with the timed task. 89 // It returns and error if the `name` is already used. 90 func (c *Cron) AddTimes(ctx context.Context, pattern string, times int, job JobFunc, name ...string) (*Entry, error) { 91 return c.AddEntry(ctx, pattern, job, times, false, name...) 92 } 93 94 // AddOnce adds a timed task which can be run only once. 95 // A unique `name` can be bound with the timed task. 96 // It returns and error if the `name` is already used. 97 func (c *Cron) AddOnce(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) { 98 return c.AddEntry(ctx, pattern, job, 1, false, name...) 99 } 100 101 // DelayAddEntry adds a timed task after `delay` time. 102 func (c *Cron) DelayAddEntry(ctx context.Context, delay time.Duration, pattern string, job JobFunc, times int, isSingleton bool, name ...string) { 103 gtimer.AddOnce(ctx, delay, func(ctx context.Context) { 104 if _, err := c.AddEntry(ctx, pattern, job, times, isSingleton, name...); err != nil { 105 panic(err) 106 } 107 }) 108 } 109 110 // DelayAdd adds a timed task after `delay` time. 111 func (c *Cron) DelayAdd(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) { 112 gtimer.AddOnce(ctx, delay, func(ctx context.Context) { 113 if _, err := c.Add(ctx, pattern, job, name...); err != nil { 114 panic(err) 115 } 116 }) 117 } 118 119 // DelayAddSingleton adds a singleton timed task after `delay` time. 120 func (c *Cron) DelayAddSingleton(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) { 121 gtimer.AddOnce(ctx, delay, func(ctx context.Context) { 122 if _, err := c.AddSingleton(ctx, pattern, job, name...); err != nil { 123 panic(err) 124 } 125 }) 126 } 127 128 // DelayAddOnce adds a timed task after `delay` time. 129 // This timed task can be run only once. 130 func (c *Cron) DelayAddOnce(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) { 131 gtimer.AddOnce(ctx, delay, func(ctx context.Context) { 132 if _, err := c.AddOnce(ctx, pattern, job, name...); err != nil { 133 panic(err) 134 } 135 }) 136 } 137 138 // DelayAddTimes adds a timed task after `delay` time. 139 // This timed task can be run specified times. 140 func (c *Cron) DelayAddTimes(ctx context.Context, delay time.Duration, pattern string, times int, job JobFunc, name ...string) { 141 gtimer.AddOnce(ctx, delay, func(ctx context.Context) { 142 if _, err := c.AddTimes(ctx, pattern, times, job, name...); err != nil { 143 panic(err) 144 } 145 }) 146 } 147 148 // Search returns a scheduled task with the specified `name`. 149 // It returns nil if not found. 150 func (c *Cron) Search(name string) *Entry { 151 if v := c.entries.Get(name); v != nil { 152 return v.(*Entry) 153 } 154 return nil 155 } 156 157 // Start starts running the specified timed task named `name`. 158 // If no`name` specified, it starts the entire cron. 159 func (c *Cron) Start(name ...string) { 160 if len(name) > 0 { 161 for _, v := range name { 162 if entry := c.Search(v); entry != nil { 163 entry.Start() 164 } 165 } 166 } else { 167 c.status.Set(StatusReady) 168 } 169 } 170 171 // Stop stops running the specified timed task named `name`. 172 // If no`name` specified, it stops the entire cron. 173 func (c *Cron) Stop(name ...string) { 174 if len(name) > 0 { 175 for _, v := range name { 176 if entry := c.Search(v); entry != nil { 177 entry.Stop() 178 } 179 } 180 } else { 181 c.status.Set(StatusStopped) 182 } 183 } 184 185 // Remove deletes scheduled task which named `name`. 186 func (c *Cron) Remove(name string) { 187 if v := c.entries.Get(name); v != nil { 188 v.(*Entry).Close() 189 } 190 } 191 192 // Close stops and closes current cron. 193 func (c *Cron) Close() { 194 c.status.Set(StatusClosed) 195 } 196 197 // Size returns the size of the timed tasks. 198 func (c *Cron) Size() int { 199 return c.entries.Size() 200 } 201 202 // Entries return all timed tasks as slice(order by registered time asc). 203 func (c *Cron) Entries() []*Entry { 204 array := garray.NewSortedArraySize(c.entries.Size(), func(v1, v2 interface{}) int { 205 entry1 := v1.(*Entry) 206 entry2 := v2.(*Entry) 207 if entry1.Time.Nanosecond() > entry2.Time.Nanosecond() { 208 return 1 209 } 210 return -1 211 }, true) 212 c.entries.RLockFunc(func(m map[string]interface{}) { 213 for _, v := range m { 214 array.Add(v.(*Entry)) 215 } 216 }) 217 entries := make([]*Entry, array.Len()) 218 array.RLockFunc(func(array []interface{}) { 219 for k, v := range array { 220 entries[k] = v.(*Entry) 221 } 222 }) 223 return entries 224 }