github.com/zhongdalu/gf@v1.0.0/g/os/gcron/gcron_cron.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf. 6 7 package gcron 8 9 import ( 10 "errors" 11 "fmt" 12 "github.com/zhongdalu/gf/g/container/garray" 13 "github.com/zhongdalu/gf/g/container/gmap" 14 "github.com/zhongdalu/gf/g/container/gtype" 15 "github.com/zhongdalu/gf/g/os/glog" 16 "github.com/zhongdalu/gf/g/os/gtimer" 17 "time" 18 ) 19 20 type Cron struct { 21 idGen *gtype.Int64 // Used for unique name generation. 22 status *gtype.Int // Timed task status(0: Not Start; 1: Running; 2: Stopped; -1: Closed) 23 entries *gmap.StrAnyMap // All timed task entries. 24 logPath *gtype.String // Logging path(folder). 25 logLevel *gtype.Int // Logging level. 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(STATUS_RUNNING), 33 entries: gmap.NewStrAnyMap(), 34 logPath: gtype.NewString(), 35 logLevel: gtype.NewInt(glog.LEVEL_PROD), 36 } 37 } 38 39 // SetLogPath sets the logging folder path. 40 func (c *Cron) SetLogPath(path string) { 41 c.logPath.Set(path) 42 } 43 44 // GetLogPath return the logging folder path. 45 func (c *Cron) GetLogPath() string { 46 return c.logPath.Val() 47 } 48 49 // SetLogLevel sets the logging level. 50 func (c *Cron) SetLogLevel(level int) { 51 c.logLevel.Set(level) 52 } 53 54 // GetLogLevel returns the logging level. 55 func (c *Cron) GetLogLevel() int { 56 return c.logLevel.Val() 57 } 58 59 // Add adds a timed task. 60 // A unique <name> can be bound with the timed task. 61 // It returns and error if the <name> is already used. 62 func (c *Cron) Add(pattern string, job func(), name ...string) (*Entry, error) { 63 if len(name) > 0 { 64 if c.Search(name[0]) != nil { 65 return nil, errors.New(fmt.Sprintf(`cron job "%s" already exists`, name[0])) 66 } 67 } 68 return c.addEntry(pattern, job, false, name...) 69 } 70 71 // AddSingleton adds a singleton timed task. 72 // A singleton timed task is that can only be running one single instance at the same time. 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) AddSingleton(pattern string, job func(), name ...string) (*Entry, error) { 76 if entry, err := c.Add(pattern, job, name...); err != nil { 77 return nil, err 78 } else { 79 entry.SetSingleton(true) 80 return entry, nil 81 } 82 } 83 84 // AddOnce adds a timed task which can be run only once. 85 // A unique <name> can be bound with the timed task. 86 // It returns and error if the <name> is already used. 87 func (c *Cron) AddOnce(pattern string, job func(), name ...string) (*Entry, error) { 88 if entry, err := c.Add(pattern, job, name...); err != nil { 89 return nil, err 90 } else { 91 entry.SetTimes(1) 92 return entry, nil 93 } 94 } 95 96 // AddTimes adds a timed task which can be run specified times. 97 // A unique <name> can be bound with the timed task. 98 // It returns and error if the <name> is already used. 99 func (c *Cron) AddTimes(pattern string, times int, job func(), name ...string) (*Entry, error) { 100 if entry, err := c.Add(pattern, job, name...); err != nil { 101 return nil, err 102 } else { 103 entry.SetTimes(times) 104 return entry, nil 105 } 106 } 107 108 // DelayAdd adds a timed task after <delay> time. 109 func (c *Cron) DelayAdd(delay time.Duration, pattern string, job func(), name ...string) { 110 gtimer.AddOnce(delay, func() { 111 if _, err := c.Add(pattern, job, name...); err != nil { 112 panic(err) 113 } 114 }) 115 } 116 117 // DelayAddSingleton adds a singleton timed task after <delay> time. 118 func (c *Cron) DelayAddSingleton(delay time.Duration, pattern string, job func(), name ...string) { 119 gtimer.AddOnce(delay, func() { 120 if _, err := c.AddSingleton(pattern, job, name...); err != nil { 121 panic(err) 122 } 123 }) 124 } 125 126 // DelayAddOnce adds a timed task after <delay> time. 127 // This timed task can be run only once. 128 func (c *Cron) DelayAddOnce(delay time.Duration, pattern string, job func(), name ...string) { 129 gtimer.AddOnce(delay, func() { 130 if _, err := c.AddOnce(pattern, job, name...); err != nil { 131 panic(err) 132 } 133 }) 134 } 135 136 // DelayAddTimes adds a timed task after <delay> time. 137 // This timed task can be run specified times. 138 func (c *Cron) DelayAddTimes(delay time.Duration, pattern string, times int, job func(), name ...string) { 139 gtimer.AddOnce(delay, func() { 140 if _, err := c.AddTimes(pattern, times, job, name...); err != nil { 141 panic(err) 142 } 143 }) 144 } 145 146 // Search returns a scheduled task with the specified <name>. 147 // It returns nil if no found. 148 func (c *Cron) Search(name string) *Entry { 149 if v := c.entries.Get(name); v != nil { 150 return v.(*Entry) 151 } 152 return nil 153 } 154 155 // Start starts running the specified timed task named <name>. 156 func (c *Cron) Start(name ...string) { 157 if len(name) > 0 { 158 for _, v := range name { 159 if entry := c.Search(v); entry != nil { 160 entry.Start() 161 } 162 } 163 } else { 164 c.status.Set(STATUS_READY) 165 } 166 } 167 168 // Stop stops running the specified timed task named <name>. 169 func (c *Cron) Stop(name ...string) { 170 if len(name) > 0 { 171 for _, v := range name { 172 if entry := c.Search(v); entry != nil { 173 entry.Stop() 174 } 175 } 176 } else { 177 c.status.Set(STATUS_STOPPED) 178 } 179 } 180 181 // Remove deletes scheduled task which named <name>. 182 func (c *Cron) Remove(name string) { 183 if v := c.entries.Get(name); v != nil { 184 v.(*Entry).Close() 185 } 186 } 187 188 // Close stops and closes current cron. 189 func (c *Cron) Close() { 190 c.status.Set(STATUS_CLOSED) 191 } 192 193 // Size returns the size of the timed tasks. 194 func (c *Cron) Size() int { 195 return c.entries.Size() 196 } 197 198 // Entries return all timed tasks as slice(order by registered time asc). 199 func (c *Cron) Entries() []*Entry { 200 array := garray.NewSortedArraySize(c.entries.Size(), func(v1, v2 interface{}) int { 201 entry1 := v1.(*Entry) 202 entry2 := v2.(*Entry) 203 if entry1.Time.Nanosecond() > entry2.Time.Nanosecond() { 204 return 1 205 } 206 return -1 207 }, true) 208 c.entries.RLockFunc(func(m map[string]interface{}) { 209 for _, v := range m { 210 array.Add(v.(*Entry)) 211 } 212 }) 213 entries := make([]*Entry, array.Len()) 214 array.RLockFunc(func(array []interface{}) { 215 for k, v := range array { 216 entries[k] = v.(*Entry) 217 } 218 }) 219 return entries 220 }