mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Adding github.com/robfig/cron for cron parsing
This commit is contained in:
		
							
								
								
									
										4
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							@@ -1760,6 +1760,10 @@
 | 
				
			|||||||
			"Comment": "v1.0.0-842-g8992d74",
 | 
								"Comment": "v1.0.0-842-g8992d74",
 | 
				
			||||||
			"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
 | 
								"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"ImportPath": "github.com/robfig/cron",
 | 
				
			||||||
 | 
								"Rev": "0f39cf7ebc65a602f45692f9894bd6a193faf8fa"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"ImportPath": "github.com/russross/blackfriday",
 | 
								"ImportPath": "github.com/russross/blackfriday",
 | 
				
			||||||
			"Comment": "v1.2-42-g77efab5",
 | 
								"Comment": "v1.2-42-g77efab5",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								Godeps/LICENSES
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										26
									
								
								Godeps/LICENSES
									
									
									
										generated
									
									
									
								
							@@ -59125,6 +59125,32 @@ specific language governing permissions and limitations under the License.
 | 
				
			|||||||
   END OF TERMS AND CONDITIONS
 | 
					   END OF TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					================================================================================
 | 
				
			||||||
 | 
					= vendor/github.com/robfig/cron licensed under: =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (C) 2012 Rob Figueiredo
 | 
				
			||||||
 | 
					All Rights Reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIT LICENSE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
				
			||||||
 | 
					this software and associated documentation files (the "Software"), to deal in
 | 
				
			||||||
 | 
					the Software without restriction, including without limitation the rights to
 | 
				
			||||||
 | 
					use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
				
			||||||
 | 
					the Software, and to permit persons to whom the Software is furnished to do so,
 | 
				
			||||||
 | 
					subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
				
			||||||
 | 
					FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
				
			||||||
 | 
					COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
				
			||||||
 | 
					IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
				
			||||||
 | 
					CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
================================================================================
 | 
					================================================================================
 | 
				
			||||||
= vendor/github.com/russross/blackfriday licensed under: =
 | 
					= vendor/github.com/russross/blackfriday licensed under: =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								vendor/github.com/robfig/cron/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/robfig/cron/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					# Compiled Object files, Static and Dynamic libs (Shared Objects)
 | 
				
			||||||
 | 
					*.o
 | 
				
			||||||
 | 
					*.a
 | 
				
			||||||
 | 
					*.so
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Folders
 | 
				
			||||||
 | 
					_obj
 | 
				
			||||||
 | 
					_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Architecture specific extensions/prefixes
 | 
				
			||||||
 | 
					*.[568vq]
 | 
				
			||||||
 | 
					[568vq].out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*.cgo1.go
 | 
				
			||||||
 | 
					*.cgo2.c
 | 
				
			||||||
 | 
					_cgo_defun.c
 | 
				
			||||||
 | 
					_cgo_gotypes.go
 | 
				
			||||||
 | 
					_cgo_export.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_testmain.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*.exe
 | 
				
			||||||
							
								
								
									
										1
									
								
								vendor/github.com/robfig/cron/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/robfig/cron/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					language: go
 | 
				
			||||||
							
								
								
									
										21
									
								
								vendor/github.com/robfig/cron/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/robfig/cron/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					Copyright (C) 2012 Rob Figueiredo
 | 
				
			||||||
 | 
					All Rights Reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIT LICENSE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
				
			||||||
 | 
					this software and associated documentation files (the "Software"), to deal in
 | 
				
			||||||
 | 
					the Software without restriction, including without limitation the rights to
 | 
				
			||||||
 | 
					use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
				
			||||||
 | 
					the Software, and to permit persons to whom the Software is furnished to do so,
 | 
				
			||||||
 | 
					subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
				
			||||||
 | 
					FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
				
			||||||
 | 
					COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
				
			||||||
 | 
					IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
				
			||||||
 | 
					CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
							
								
								
									
										2
									
								
								vendor/github.com/robfig/cron/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/robfig/cron/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					[](http://godoc.org/github.com/robfig/cron)
 | 
				
			||||||
 | 
					[](https://travis-ci.org/robfig/cron)
 | 
				
			||||||
							
								
								
									
										27
									
								
								vendor/github.com/robfig/cron/constantdelay.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/robfig/cron/constantdelay.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					package cron
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes".
 | 
				
			||||||
 | 
					// It does not support jobs more frequent than once a second.
 | 
				
			||||||
 | 
					type ConstantDelaySchedule struct {
 | 
				
			||||||
 | 
						Delay time.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Every returns a crontab Schedule that activates once every duration.
 | 
				
			||||||
 | 
					// Delays of less than a second are not supported (will round up to 1 second).
 | 
				
			||||||
 | 
					// Any fields less than a Second are truncated.
 | 
				
			||||||
 | 
					func Every(duration time.Duration) ConstantDelaySchedule {
 | 
				
			||||||
 | 
						if duration < time.Second {
 | 
				
			||||||
 | 
							duration = time.Second
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ConstantDelaySchedule{
 | 
				
			||||||
 | 
							Delay: duration - time.Duration(duration.Nanoseconds())%time.Second,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Next returns the next time this should be run.
 | 
				
			||||||
 | 
					// This rounds so that the next activation time will be on the second.
 | 
				
			||||||
 | 
					func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time {
 | 
				
			||||||
 | 
						return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										227
									
								
								vendor/github.com/robfig/cron/cron.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								vendor/github.com/robfig/cron/cron.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,227 @@
 | 
				
			|||||||
 | 
					// This library implements a cron spec parser and runner.  See the README for
 | 
				
			||||||
 | 
					// more details.
 | 
				
			||||||
 | 
					package cron
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Cron keeps track of any number of entries, invoking the associated func as
 | 
				
			||||||
 | 
					// specified by the schedule. It may be started, stopped, and the entries may
 | 
				
			||||||
 | 
					// be inspected while running.
 | 
				
			||||||
 | 
					type Cron struct {
 | 
				
			||||||
 | 
						entries  []*Entry
 | 
				
			||||||
 | 
						stop     chan struct{}
 | 
				
			||||||
 | 
						add      chan *Entry
 | 
				
			||||||
 | 
						snapshot chan []*Entry
 | 
				
			||||||
 | 
						running  bool
 | 
				
			||||||
 | 
						ErrorLog *log.Logger
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Job is an interface for submitted cron jobs.
 | 
				
			||||||
 | 
					type Job interface {
 | 
				
			||||||
 | 
						Run()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The Schedule describes a job's duty cycle.
 | 
				
			||||||
 | 
					type Schedule interface {
 | 
				
			||||||
 | 
						// Return the next activation time, later than the given time.
 | 
				
			||||||
 | 
						// Next is invoked initially, and then each time the job is run.
 | 
				
			||||||
 | 
						Next(time.Time) time.Time
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Entry consists of a schedule and the func to execute on that schedule.
 | 
				
			||||||
 | 
					type Entry struct {
 | 
				
			||||||
 | 
						// The schedule on which this job should be run.
 | 
				
			||||||
 | 
						Schedule Schedule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The next time the job will run. This is the zero time if Cron has not been
 | 
				
			||||||
 | 
						// started or this entry's schedule is unsatisfiable
 | 
				
			||||||
 | 
						Next time.Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The last time this job was run. This is the zero time if the job has never
 | 
				
			||||||
 | 
						// been run.
 | 
				
			||||||
 | 
						Prev time.Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The Job to run.
 | 
				
			||||||
 | 
						Job Job
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// byTime is a wrapper for sorting the entry array by time
 | 
				
			||||||
 | 
					// (with zero time at the end).
 | 
				
			||||||
 | 
					type byTime []*Entry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s byTime) Len() int      { return len(s) }
 | 
				
			||||||
 | 
					func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
 | 
				
			||||||
 | 
					func (s byTime) Less(i, j int) bool {
 | 
				
			||||||
 | 
						// Two zero times should return false.
 | 
				
			||||||
 | 
						// Otherwise, zero is "greater" than any other time.
 | 
				
			||||||
 | 
						// (To sort it at the end of the list.)
 | 
				
			||||||
 | 
						if s[i].Next.IsZero() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if s[j].Next.IsZero() {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s[i].Next.Before(s[j].Next)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// New returns a new Cron job runner.
 | 
				
			||||||
 | 
					func New() *Cron {
 | 
				
			||||||
 | 
						return &Cron{
 | 
				
			||||||
 | 
							entries:  nil,
 | 
				
			||||||
 | 
							add:      make(chan *Entry),
 | 
				
			||||||
 | 
							stop:     make(chan struct{}),
 | 
				
			||||||
 | 
							snapshot: make(chan []*Entry),
 | 
				
			||||||
 | 
							running:  false,
 | 
				
			||||||
 | 
							ErrorLog: nil,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A wrapper that turns a func() into a cron.Job
 | 
				
			||||||
 | 
					type FuncJob func()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f FuncJob) Run() { f() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddFunc adds a func to the Cron to be run on the given schedule.
 | 
				
			||||||
 | 
					func (c *Cron) AddFunc(spec string, cmd func()) error {
 | 
				
			||||||
 | 
						return c.AddJob(spec, FuncJob(cmd))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddJob adds a Job to the Cron to be run on the given schedule.
 | 
				
			||||||
 | 
					func (c *Cron) AddJob(spec string, cmd Job) error {
 | 
				
			||||||
 | 
						schedule, err := Parse(spec)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Schedule(schedule, cmd)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Schedule adds a Job to the Cron to be run on the given schedule.
 | 
				
			||||||
 | 
					func (c *Cron) Schedule(schedule Schedule, cmd Job) {
 | 
				
			||||||
 | 
						entry := &Entry{
 | 
				
			||||||
 | 
							Schedule: schedule,
 | 
				
			||||||
 | 
							Job:      cmd,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !c.running {
 | 
				
			||||||
 | 
							c.entries = append(c.entries, entry)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.add <- entry
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Entries returns a snapshot of the cron entries.
 | 
				
			||||||
 | 
					func (c *Cron) Entries() []*Entry {
 | 
				
			||||||
 | 
						if c.running {
 | 
				
			||||||
 | 
							c.snapshot <- nil
 | 
				
			||||||
 | 
							x := <-c.snapshot
 | 
				
			||||||
 | 
							return x
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return c.entrySnapshot()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Start the cron scheduler in its own go-routine.
 | 
				
			||||||
 | 
					func (c *Cron) Start() {
 | 
				
			||||||
 | 
						c.running = true
 | 
				
			||||||
 | 
						go c.run()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cron) runWithRecovery(j Job) {
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if r := recover(); r != nil {
 | 
				
			||||||
 | 
								const size = 64 << 10
 | 
				
			||||||
 | 
								buf := make([]byte, size)
 | 
				
			||||||
 | 
								buf = buf[:runtime.Stack(buf, false)]
 | 
				
			||||||
 | 
								c.logf("cron: panic running job: %v\n%s", r, buf)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						j.Run()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Run the scheduler.. this is private just due to the need to synchronize
 | 
				
			||||||
 | 
					// access to the 'running' state variable.
 | 
				
			||||||
 | 
					func (c *Cron) run() {
 | 
				
			||||||
 | 
						// Figure out the next activation times for each entry.
 | 
				
			||||||
 | 
						now := time.Now().Local()
 | 
				
			||||||
 | 
						for _, entry := range c.entries {
 | 
				
			||||||
 | 
							entry.Next = entry.Schedule.Next(now)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							// Determine the next entry to run.
 | 
				
			||||||
 | 
							sort.Sort(byTime(c.entries))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var effective time.Time
 | 
				
			||||||
 | 
							if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
 | 
				
			||||||
 | 
								// If there are no entries yet, just sleep - it still handles new entries
 | 
				
			||||||
 | 
								// and stop requests.
 | 
				
			||||||
 | 
								effective = now.AddDate(10, 0, 0)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								effective = c.entries[0].Next
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case now = <-time.After(effective.Sub(now)):
 | 
				
			||||||
 | 
								// Run every entry whose next time was this effective time.
 | 
				
			||||||
 | 
								for _, e := range c.entries {
 | 
				
			||||||
 | 
									if e.Next != effective {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									go c.runWithRecovery(e.Job)
 | 
				
			||||||
 | 
									e.Prev = e.Next
 | 
				
			||||||
 | 
									e.Next = e.Schedule.Next(effective)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case newEntry := <-c.add:
 | 
				
			||||||
 | 
								c.entries = append(c.entries, newEntry)
 | 
				
			||||||
 | 
								newEntry.Next = newEntry.Schedule.Next(time.Now().Local())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case <-c.snapshot:
 | 
				
			||||||
 | 
								c.snapshot <- c.entrySnapshot()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case <-c.stop:
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 'now' should be updated after newEntry and snapshot cases.
 | 
				
			||||||
 | 
							now = time.Now().Local()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Logs an error to stderr or to the configured error log
 | 
				
			||||||
 | 
					func (c *Cron) logf(format string, args ...interface{}) {
 | 
				
			||||||
 | 
						if c.ErrorLog != nil {
 | 
				
			||||||
 | 
							c.ErrorLog.Printf(format, args...)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							log.Printf(format, args...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Stop stops the cron scheduler if it is running; otherwise it does nothing.
 | 
				
			||||||
 | 
					func (c *Cron) Stop() {
 | 
				
			||||||
 | 
						if !c.running {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.stop <- struct{}{}
 | 
				
			||||||
 | 
						c.running = false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// entrySnapshot returns a copy of the current cron entry list.
 | 
				
			||||||
 | 
					func (c *Cron) entrySnapshot() []*Entry {
 | 
				
			||||||
 | 
						entries := []*Entry{}
 | 
				
			||||||
 | 
						for _, e := range c.entries {
 | 
				
			||||||
 | 
							entries = append(entries, &Entry{
 | 
				
			||||||
 | 
								Schedule: e.Schedule,
 | 
				
			||||||
 | 
								Next:     e.Next,
 | 
				
			||||||
 | 
								Prev:     e.Prev,
 | 
				
			||||||
 | 
								Job:      e.Job,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return entries
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										129
									
								
								vendor/github.com/robfig/cron/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								vendor/github.com/robfig/cron/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Package cron implements a cron spec parser and job runner.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Callers may register Funcs to be invoked on a given schedule.  Cron will run
 | 
				
			||||||
 | 
					them in their own goroutines.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c := cron.New()
 | 
				
			||||||
 | 
						c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
 | 
				
			||||||
 | 
						c.AddFunc("@hourly",      func() { fmt.Println("Every hour") })
 | 
				
			||||||
 | 
						c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
 | 
				
			||||||
 | 
						c.Start()
 | 
				
			||||||
 | 
						..
 | 
				
			||||||
 | 
						// Funcs are invoked in their own goroutine, asynchronously.
 | 
				
			||||||
 | 
						...
 | 
				
			||||||
 | 
						// Funcs may also be added to a running Cron
 | 
				
			||||||
 | 
						c.AddFunc("@daily", func() { fmt.Println("Every day") })
 | 
				
			||||||
 | 
						..
 | 
				
			||||||
 | 
						// Inspect the cron job entries' next and previous run times.
 | 
				
			||||||
 | 
						inspect(c.Entries())
 | 
				
			||||||
 | 
						..
 | 
				
			||||||
 | 
						c.Stop()  // Stop the scheduler (does not stop any jobs already running).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CRON Expression Format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A cron expression represents a set of times, using 6 space-separated fields.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Field name   | Mandatory? | Allowed values  | Allowed special characters
 | 
				
			||||||
 | 
						----------   | ---------- | --------------  | --------------------------
 | 
				
			||||||
 | 
						Seconds      | Yes        | 0-59            | * / , -
 | 
				
			||||||
 | 
						Minutes      | Yes        | 0-59            | * / , -
 | 
				
			||||||
 | 
						Hours        | Yes        | 0-23            | * / , -
 | 
				
			||||||
 | 
						Day of month | Yes        | 1-31            | * / , - ?
 | 
				
			||||||
 | 
						Month        | Yes        | 1-12 or JAN-DEC | * / , -
 | 
				
			||||||
 | 
						Day of week  | Yes        | 0-6 or SUN-SAT  | * / , - ?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note: Month and Day-of-week field values are case insensitive.  "SUN", "Sun",
 | 
				
			||||||
 | 
					and "sun" are equally accepted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Special Characters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Asterisk ( * )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The asterisk indicates that the cron expression will match for all values of the
 | 
				
			||||||
 | 
					field; e.g., using an asterisk in the 5th field (month) would indicate every
 | 
				
			||||||
 | 
					month.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Slash ( / )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Slashes are used to describe increments of ranges. For example 3-59/15 in the
 | 
				
			||||||
 | 
					1st field (minutes) would indicate the 3rd minute of the hour and every 15
 | 
				
			||||||
 | 
					minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...",
 | 
				
			||||||
 | 
					that is, an increment over the largest possible range of the field.  The form
 | 
				
			||||||
 | 
					"N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the
 | 
				
			||||||
 | 
					increment until the end of that specific range.  It does not wrap around.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Comma ( , )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Commas are used to separate items of a list. For example, using "MON,WED,FRI" in
 | 
				
			||||||
 | 
					the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hyphen ( - )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hyphens are used to define ranges. For example, 9-17 would indicate every
 | 
				
			||||||
 | 
					hour between 9am and 5pm inclusive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Question mark ( ? )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Question mark may be used instead of '*' for leaving either day-of-month or
 | 
				
			||||||
 | 
					day-of-week blank.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Predefined schedules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You may use one of several pre-defined schedules in place of a cron expression.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Entry                  | Description                                | Equivalent To
 | 
				
			||||||
 | 
						-----                  | -----------                                | -------------
 | 
				
			||||||
 | 
						@yearly (or @annually) | Run once a year, midnight, Jan. 1st        | 0 0 0 1 1 *
 | 
				
			||||||
 | 
						@monthly               | Run once a month, midnight, first of month | 0 0 0 1 * *
 | 
				
			||||||
 | 
						@weekly                | Run once a week, midnight on Sunday        | 0 0 0 * * 0
 | 
				
			||||||
 | 
						@daily (or @midnight)  | Run once a day, midnight                   | 0 0 0 * * *
 | 
				
			||||||
 | 
						@hourly                | Run once an hour, beginning of hour        | 0 0 * * * *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Intervals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You may also schedule a job to execute at fixed intervals.  This is supported by
 | 
				
			||||||
 | 
					formatting the cron spec like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @every <duration>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					where "duration" is a string accepted by time.ParseDuration
 | 
				
			||||||
 | 
					(http://golang.org/pkg/time/#ParseDuration).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For example, "@every 1h30m10s" would indicate a schedule that activates every
 | 
				
			||||||
 | 
					1 hour, 30 minutes, 10 seconds.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note: The interval does not take the job runtime into account.  For example,
 | 
				
			||||||
 | 
					if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes,
 | 
				
			||||||
 | 
					it will have only 2 minutes of idle time between each run.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time zones
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All interpretation and scheduling is done in the machine's local time zone (as
 | 
				
			||||||
 | 
					provided by the Go time package (http://www.golang.org/pkg/time).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Be aware that jobs scheduled during daylight-savings leap-ahead transitions will
 | 
				
			||||||
 | 
					not be run!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thread safety
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since the Cron service runs concurrently with the calling code, some amount of
 | 
				
			||||||
 | 
					care must be taken to ensure proper synchronization.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All cron methods are designed to be correctly synchronized as long as the caller
 | 
				
			||||||
 | 
					ensures that invocations have a clear happens-before ordering between them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Implementation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Cron entries are stored in an array, sorted by their next activation time.  Cron
 | 
				
			||||||
 | 
					sleeps until the next job is due to be run.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Upon waking:
 | 
				
			||||||
 | 
					 - it runs each entry that is active on that second
 | 
				
			||||||
 | 
					 - it calculates the next run times for the jobs that were run
 | 
				
			||||||
 | 
					 - it re-sorts the array of entries by next activation time.
 | 
				
			||||||
 | 
					 - it goes to sleep until the soonest job.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package cron
 | 
				
			||||||
							
								
								
									
										231
									
								
								vendor/github.com/robfig/cron/parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								vendor/github.com/robfig/cron/parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
				
			|||||||
 | 
					package cron
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Parse returns a new crontab schedule representing the given spec.
 | 
				
			||||||
 | 
					// It returns a descriptive error if the spec is not valid.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// It accepts
 | 
				
			||||||
 | 
					//   - Full crontab specs, e.g. "* * * * * ?"
 | 
				
			||||||
 | 
					//   - Descriptors, e.g. "@midnight", "@every 1h30m"
 | 
				
			||||||
 | 
					func Parse(spec string) (_ Schedule, err error) {
 | 
				
			||||||
 | 
						// Convert panics into errors
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if recovered := recover(); recovered != nil {
 | 
				
			||||||
 | 
								err = fmt.Errorf("%v", recovered)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if spec[0] == '@' {
 | 
				
			||||||
 | 
							return parseDescriptor(spec), nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Split on whitespace.  We require 5 or 6 fields.
 | 
				
			||||||
 | 
						// (second) (minute) (hour) (day of month) (month) (day of week, optional)
 | 
				
			||||||
 | 
						fields := strings.Fields(spec)
 | 
				
			||||||
 | 
						if len(fields) != 5 && len(fields) != 6 {
 | 
				
			||||||
 | 
							log.Panicf("Expected 5 or 6 fields, found %d: %s", len(fields), spec)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If a sixth field is not provided (DayOfWeek), then it is equivalent to star.
 | 
				
			||||||
 | 
						if len(fields) == 5 {
 | 
				
			||||||
 | 
							fields = append(fields, "*")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						schedule := &SpecSchedule{
 | 
				
			||||||
 | 
							Second: getField(fields[0], seconds),
 | 
				
			||||||
 | 
							Minute: getField(fields[1], minutes),
 | 
				
			||||||
 | 
							Hour:   getField(fields[2], hours),
 | 
				
			||||||
 | 
							Dom:    getField(fields[3], dom),
 | 
				
			||||||
 | 
							Month:  getField(fields[4], months),
 | 
				
			||||||
 | 
							Dow:    getField(fields[5], dow),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return schedule, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getField returns an Int with the bits set representing all of the times that
 | 
				
			||||||
 | 
					// the field represents.  A "field" is a comma-separated list of "ranges".
 | 
				
			||||||
 | 
					func getField(field string, r bounds) uint64 {
 | 
				
			||||||
 | 
						// list = range {"," range}
 | 
				
			||||||
 | 
						var bits uint64
 | 
				
			||||||
 | 
						ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' })
 | 
				
			||||||
 | 
						for _, expr := range ranges {
 | 
				
			||||||
 | 
							bits |= getRange(expr, r)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return bits
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getRange returns the bits indicated by the given expression:
 | 
				
			||||||
 | 
					//   number | number "-" number [ "/" number ]
 | 
				
			||||||
 | 
					func getRange(expr string, r bounds) uint64 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							start, end, step uint
 | 
				
			||||||
 | 
							rangeAndStep     = strings.Split(expr, "/")
 | 
				
			||||||
 | 
							lowAndHigh       = strings.Split(rangeAndStep[0], "-")
 | 
				
			||||||
 | 
							singleDigit      = len(lowAndHigh) == 1
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var extra_star uint64
 | 
				
			||||||
 | 
						if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" {
 | 
				
			||||||
 | 
							start = r.min
 | 
				
			||||||
 | 
							end = r.max
 | 
				
			||||||
 | 
							extra_star = starBit
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							start = parseIntOrName(lowAndHigh[0], r.names)
 | 
				
			||||||
 | 
							switch len(lowAndHigh) {
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								end = start
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								end = parseIntOrName(lowAndHigh[1], r.names)
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								log.Panicf("Too many hyphens: %s", expr)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch len(rangeAndStep) {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							step = 1
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							step = mustParseInt(rangeAndStep[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Special handling: "N/step" means "N-max/step".
 | 
				
			||||||
 | 
							if singleDigit {
 | 
				
			||||||
 | 
								end = r.max
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							log.Panicf("Too many slashes: %s", expr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if start < r.min {
 | 
				
			||||||
 | 
							log.Panicf("Beginning of range (%d) below minimum (%d): %s", start, r.min, expr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if end > r.max {
 | 
				
			||||||
 | 
							log.Panicf("End of range (%d) above maximum (%d): %s", end, r.max, expr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if start > end {
 | 
				
			||||||
 | 
							log.Panicf("Beginning of range (%d) beyond end of range (%d): %s", start, end, expr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return getBits(start, end, step) | extra_star
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// parseIntOrName returns the (possibly-named) integer contained in expr.
 | 
				
			||||||
 | 
					func parseIntOrName(expr string, names map[string]uint) uint {
 | 
				
			||||||
 | 
						if names != nil {
 | 
				
			||||||
 | 
							if namedInt, ok := names[strings.ToLower(expr)]; ok {
 | 
				
			||||||
 | 
								return namedInt
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return mustParseInt(expr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// mustParseInt parses the given expression as an int or panics.
 | 
				
			||||||
 | 
					func mustParseInt(expr string) uint {
 | 
				
			||||||
 | 
						num, err := strconv.Atoi(expr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Panicf("Failed to parse int from %s: %s", expr, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if num < 0 {
 | 
				
			||||||
 | 
							log.Panicf("Negative number (%d) not allowed: %s", num, expr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return uint(num)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getBits sets all bits in the range [min, max], modulo the given step size.
 | 
				
			||||||
 | 
					func getBits(min, max, step uint) uint64 {
 | 
				
			||||||
 | 
						var bits uint64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If step is 1, use shifts.
 | 
				
			||||||
 | 
						if step == 1 {
 | 
				
			||||||
 | 
							return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Else, use a simple loop.
 | 
				
			||||||
 | 
						for i := min; i <= max; i += step {
 | 
				
			||||||
 | 
							bits |= 1 << i
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return bits
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// all returns all bits within the given bounds.  (plus the star bit)
 | 
				
			||||||
 | 
					func all(r bounds) uint64 {
 | 
				
			||||||
 | 
						return getBits(r.min, r.max, 1) | starBit
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// parseDescriptor returns a pre-defined schedule for the expression, or panics
 | 
				
			||||||
 | 
					// if none matches.
 | 
				
			||||||
 | 
					func parseDescriptor(spec string) Schedule {
 | 
				
			||||||
 | 
						switch spec {
 | 
				
			||||||
 | 
						case "@yearly", "@annually":
 | 
				
			||||||
 | 
							return &SpecSchedule{
 | 
				
			||||||
 | 
								Second: 1 << seconds.min,
 | 
				
			||||||
 | 
								Minute: 1 << minutes.min,
 | 
				
			||||||
 | 
								Hour:   1 << hours.min,
 | 
				
			||||||
 | 
								Dom:    1 << dom.min,
 | 
				
			||||||
 | 
								Month:  1 << months.min,
 | 
				
			||||||
 | 
								Dow:    all(dow),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case "@monthly":
 | 
				
			||||||
 | 
							return &SpecSchedule{
 | 
				
			||||||
 | 
								Second: 1 << seconds.min,
 | 
				
			||||||
 | 
								Minute: 1 << minutes.min,
 | 
				
			||||||
 | 
								Hour:   1 << hours.min,
 | 
				
			||||||
 | 
								Dom:    1 << dom.min,
 | 
				
			||||||
 | 
								Month:  all(months),
 | 
				
			||||||
 | 
								Dow:    all(dow),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case "@weekly":
 | 
				
			||||||
 | 
							return &SpecSchedule{
 | 
				
			||||||
 | 
								Second: 1 << seconds.min,
 | 
				
			||||||
 | 
								Minute: 1 << minutes.min,
 | 
				
			||||||
 | 
								Hour:   1 << hours.min,
 | 
				
			||||||
 | 
								Dom:    all(dom),
 | 
				
			||||||
 | 
								Month:  all(months),
 | 
				
			||||||
 | 
								Dow:    1 << dow.min,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case "@daily", "@midnight":
 | 
				
			||||||
 | 
							return &SpecSchedule{
 | 
				
			||||||
 | 
								Second: 1 << seconds.min,
 | 
				
			||||||
 | 
								Minute: 1 << minutes.min,
 | 
				
			||||||
 | 
								Hour:   1 << hours.min,
 | 
				
			||||||
 | 
								Dom:    all(dom),
 | 
				
			||||||
 | 
								Month:  all(months),
 | 
				
			||||||
 | 
								Dow:    all(dow),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case "@hourly":
 | 
				
			||||||
 | 
							return &SpecSchedule{
 | 
				
			||||||
 | 
								Second: 1 << seconds.min,
 | 
				
			||||||
 | 
								Minute: 1 << minutes.min,
 | 
				
			||||||
 | 
								Hour:   all(hours),
 | 
				
			||||||
 | 
								Dom:    all(dom),
 | 
				
			||||||
 | 
								Month:  all(months),
 | 
				
			||||||
 | 
								Dow:    all(dow),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const every = "@every "
 | 
				
			||||||
 | 
						if strings.HasPrefix(spec, every) {
 | 
				
			||||||
 | 
							duration, err := time.ParseDuration(spec[len(every):])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Panicf("Failed to parse duration %s: %s", spec, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return Every(duration)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Panicf("Unrecognized descriptor: %s", spec)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										159
									
								
								vendor/github.com/robfig/cron/spec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								vendor/github.com/robfig/cron/spec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
				
			|||||||
 | 
					package cron
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SpecSchedule specifies a duty cycle (to the second granularity), based on a
 | 
				
			||||||
 | 
					// traditional crontab specification. It is computed initially and stored as bit sets.
 | 
				
			||||||
 | 
					type SpecSchedule struct {
 | 
				
			||||||
 | 
						Second, Minute, Hour, Dom, Month, Dow uint64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// bounds provides a range of acceptable values (plus a map of name to value).
 | 
				
			||||||
 | 
					type bounds struct {
 | 
				
			||||||
 | 
						min, max uint
 | 
				
			||||||
 | 
						names    map[string]uint
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The bounds for each field.
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						seconds = bounds{0, 59, nil}
 | 
				
			||||||
 | 
						minutes = bounds{0, 59, nil}
 | 
				
			||||||
 | 
						hours   = bounds{0, 23, nil}
 | 
				
			||||||
 | 
						dom     = bounds{1, 31, nil}
 | 
				
			||||||
 | 
						months  = bounds{1, 12, map[string]uint{
 | 
				
			||||||
 | 
							"jan": 1,
 | 
				
			||||||
 | 
							"feb": 2,
 | 
				
			||||||
 | 
							"mar": 3,
 | 
				
			||||||
 | 
							"apr": 4,
 | 
				
			||||||
 | 
							"may": 5,
 | 
				
			||||||
 | 
							"jun": 6,
 | 
				
			||||||
 | 
							"jul": 7,
 | 
				
			||||||
 | 
							"aug": 8,
 | 
				
			||||||
 | 
							"sep": 9,
 | 
				
			||||||
 | 
							"oct": 10,
 | 
				
			||||||
 | 
							"nov": 11,
 | 
				
			||||||
 | 
							"dec": 12,
 | 
				
			||||||
 | 
						}}
 | 
				
			||||||
 | 
						dow = bounds{0, 6, map[string]uint{
 | 
				
			||||||
 | 
							"sun": 0,
 | 
				
			||||||
 | 
							"mon": 1,
 | 
				
			||||||
 | 
							"tue": 2,
 | 
				
			||||||
 | 
							"wed": 3,
 | 
				
			||||||
 | 
							"thu": 4,
 | 
				
			||||||
 | 
							"fri": 5,
 | 
				
			||||||
 | 
							"sat": 6,
 | 
				
			||||||
 | 
						}}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// Set the top bit if a star was included in the expression.
 | 
				
			||||||
 | 
						starBit = 1 << 63
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Next returns the next time this schedule is activated, greater than the given
 | 
				
			||||||
 | 
					// time.  If no time can be found to satisfy the schedule, return the zero time.
 | 
				
			||||||
 | 
					func (s *SpecSchedule) Next(t time.Time) time.Time {
 | 
				
			||||||
 | 
						// General approach:
 | 
				
			||||||
 | 
						// For Month, Day, Hour, Minute, Second:
 | 
				
			||||||
 | 
						// Check if the time value matches.  If yes, continue to the next field.
 | 
				
			||||||
 | 
						// If the field doesn't match the schedule, then increment the field until it matches.
 | 
				
			||||||
 | 
						// While incrementing the field, a wrap-around brings it back to the beginning
 | 
				
			||||||
 | 
						// of the field list (since it is necessary to re-verify previous field
 | 
				
			||||||
 | 
						// values)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Start at the earliest possible time (the upcoming second).
 | 
				
			||||||
 | 
						t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This flag indicates whether a field has been incremented.
 | 
				
			||||||
 | 
						added := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If no time is found within five years, return zero.
 | 
				
			||||||
 | 
						yearLimit := t.Year() + 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WRAP:
 | 
				
			||||||
 | 
						if t.Year() > yearLimit {
 | 
				
			||||||
 | 
							return time.Time{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Find the first applicable month.
 | 
				
			||||||
 | 
						// If it's this month, then do nothing.
 | 
				
			||||||
 | 
						for 1<<uint(t.Month())&s.Month == 0 {
 | 
				
			||||||
 | 
							// If we have to add a month, reset the other parts to 0.
 | 
				
			||||||
 | 
							if !added {
 | 
				
			||||||
 | 
								added = true
 | 
				
			||||||
 | 
								// Otherwise, set the date at the beginning (since the current time is irrelevant).
 | 
				
			||||||
 | 
								t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t = t.AddDate(0, 1, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Wrapped around.
 | 
				
			||||||
 | 
							if t.Month() == time.January {
 | 
				
			||||||
 | 
								goto WRAP
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Now get a day in that month.
 | 
				
			||||||
 | 
						for !dayMatches(s, t) {
 | 
				
			||||||
 | 
							if !added {
 | 
				
			||||||
 | 
								added = true
 | 
				
			||||||
 | 
								t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t = t.AddDate(0, 0, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if t.Day() == 1 {
 | 
				
			||||||
 | 
								goto WRAP
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for 1<<uint(t.Hour())&s.Hour == 0 {
 | 
				
			||||||
 | 
							if !added {
 | 
				
			||||||
 | 
								added = true
 | 
				
			||||||
 | 
								t = t.Truncate(time.Hour)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t = t.Add(1 * time.Hour)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if t.Hour() == 0 {
 | 
				
			||||||
 | 
								goto WRAP
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for 1<<uint(t.Minute())&s.Minute == 0 {
 | 
				
			||||||
 | 
							if !added {
 | 
				
			||||||
 | 
								added = true
 | 
				
			||||||
 | 
								t = t.Truncate(time.Minute)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t = t.Add(1 * time.Minute)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if t.Minute() == 0 {
 | 
				
			||||||
 | 
								goto WRAP
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for 1<<uint(t.Second())&s.Second == 0 {
 | 
				
			||||||
 | 
							if !added {
 | 
				
			||||||
 | 
								added = true
 | 
				
			||||||
 | 
								t = t.Truncate(time.Second)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t = t.Add(1 * time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if t.Second() == 0 {
 | 
				
			||||||
 | 
								goto WRAP
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return t
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// dayMatches returns true if the schedule's day-of-week and day-of-month
 | 
				
			||||||
 | 
					// restrictions are satisfied by the given time.
 | 
				
			||||||
 | 
					func dayMatches(s *SpecSchedule, t time.Time) bool {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							domMatch bool = 1<<uint(t.Day())&s.Dom > 0
 | 
				
			||||||
 | 
							dowMatch bool = 1<<uint(t.Weekday())&s.Dow > 0
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if s.Dom&starBit > 0 || s.Dow&starBit > 0 {
 | 
				
			||||||
 | 
							return domMatch && dowMatch
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return domMatch || dowMatch
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user