-
Notifications
You must be signed in to change notification settings - Fork 343
/
gocron.go
134 lines (117 loc) · 3.61 KB
/
gocron.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Package gocron : A Golang Job Scheduling Package.
//
// Note from current maintainers:
//
// A currently maintained fork of this project has been migrated to https://github.com/go-co-op/gocron
//
// Disclaimer: we (the maintainers) tried, with no luck, to get in contact with Jason (the repository owner) in order to add new maintainers or leave the project within an organization. Unfortunately, he hasn't replied for months now (March, 2020).
//
// So, we decided to move the project to a new repository (as stated above), in order to keep the evolution of the project coming from as many people as possible. Feel free to reach over!
//
// An in-process scheduler for periodic jobs that uses the builder pattern
// for configuration. Schedule lets you run Golang functions periodically
// at pre-determined intervals using a simple, human-friendly syntax.
//
// Inspired by the Ruby module clockwork <https://github.com/tomykaira/clockwork>
// and
// Python package schedule <https://github.com/dbader/schedule>
//
// See also
// http://adam.heroku.com/past/2010/4/13/rethinking_cron/
// http://adam.heroku.com/past/2010/6/30/replace_cron_with_clockwork/
//
// Copyright 2014 Jason Lyu. [email protected] .
// All rights reserved.
// Use of this source code is governed by a BSD-style .
// license that can be found in the LICENSE file.
package gocron
import (
"crypto/sha256"
"fmt"
"reflect"
"runtime"
"strconv"
"strings"
"time"
)
// Locker provides a method to lock jobs from running
// at the same time on multiple instances of gocron.
// You can provide any locker implementation you wish.
type Locker interface {
Lock(key string) (bool, error)
Unlock(key string) error
}
type timeUnit int
// MAXJOBNUM max number of jobs, hack it if you need.
const MAXJOBNUM = 10000
//go:generate stringer -type=timeUnit
const (
seconds timeUnit = iota + 1
minutes
hours
days
weeks
)
var (
loc = time.Local // Time location, default set by the time.Local (*time.Location)
locker Locker
)
// ChangeLoc change default the time location
func ChangeLoc(newLocation *time.Location) {
loc = newLocation
defaultScheduler.ChangeLoc(newLocation)
}
// SetLocker sets a locker implementation
func SetLocker(l Locker) {
locker = l
}
func callJobFuncWithParams(jobFunc interface{}, params []interface{}) ([]reflect.Value, error) {
f := reflect.ValueOf(jobFunc)
if len(params) != f.Type().NumIn() {
return nil, ErrParamsNotAdapted
}
in := make([]reflect.Value, len(params))
for k, param := range params {
in[k] = reflect.ValueOf(param)
}
return f.Call(in), nil
}
// for given function fn, get the name of function.
func getFunctionName(fn interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
}
func getFunctionKey(funcName string) string {
h := sha256.New()
h.Write([]byte(funcName))
return fmt.Sprintf("%x", h.Sum(nil))
}
// Jobs returns the list of Jobs from the defaultScheduler
func Jobs() []*Job {
return defaultScheduler.Jobs()
}
func formatTime(t string) (hour, min, sec int, err error) {
ts := strings.Split(t, ":")
if len(ts) < 2 || len(ts) > 3 {
return 0, 0, 0, ErrTimeFormat
}
if hour, err = strconv.Atoi(ts[0]); err != nil {
return 0, 0, 0, err
}
if min, err = strconv.Atoi(ts[1]); err != nil {
return 0, 0, 0, err
}
if len(ts) == 3 {
if sec, err = strconv.Atoi(ts[2]); err != nil {
return 0, 0, 0, err
}
}
if hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59 {
return 0, 0, 0, ErrTimeFormat
}
return hour, min, sec, nil
}
// NextTick returns a pointer to a time that will run at the next tick
func NextTick() *time.Time {
now := time.Now().Add(time.Second)
return &now
}