mirror of
https://github.com/Fishwaldo/sched.git
synced 2025-03-15 11:31:29 +00:00
Add Documentation Comments
Signed-off-by: Sherif Abdel-Naby <sherifabdlnaby@gmail.com>
This commit is contained in:
parent
b3d39cffc1
commit
cb8f233b4d
12 changed files with 124 additions and 8 deletions
|
@ -56,7 +56,7 @@ linters-settings:
|
|||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
min-confidence: 0.1
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
|
@ -133,6 +133,7 @@ linters:
|
|||
- varcheck
|
||||
- bodyclose
|
||||
- depguard
|
||||
- golint
|
||||
- dupl
|
||||
- govet
|
||||
- gochecknoinits
|
||||
|
|
2
go.mod
2
go.mod
|
@ -14,4 +14,6 @@ require (
|
|||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/uber-go/tally v3.3.17+incompatible
|
||||
go.uber.org/zap v1.16.0
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
|
||||
golang.org/x/tools v0.1.0 // indirect
|
||||
)
|
||||
|
|
19
go.sum
19
go.sum
|
@ -40,6 +40,7 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
|||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/uber-go/tally v3.3.17+incompatible h1:nFHIuW3VQ22wItiE9kPXic8dEgExWOsVOHwpmoIvsMw=
|
||||
github.com/uber-go/tally v3.3.17+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyufu1cEi0jdVnRdxvjnmU=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
|
||||
|
@ -50,24 +51,42 @@ go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
|
|||
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package job
|
||||
|
||||
//ErrorJobPanic Error returned when a Job panics
|
||||
type ErrorJobPanic struct {
|
||||
Message string
|
||||
}
|
||||
|
@ -12,6 +13,7 @@ func (e ErrorJobPanic) Unwrap() error {
|
|||
return e
|
||||
}
|
||||
|
||||
//ErrorJobStarted Error returned when a has already started.
|
||||
type ErrorJobStarted struct {
|
||||
Message string
|
||||
}
|
||||
|
|
15
job/job.go
15
job/job.go
|
@ -8,6 +8,9 @@ import (
|
|||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
//Job Wraps JobFun and provide:
|
||||
// 1. Creation, Start, and Finish Time
|
||||
// 2. Recover From Panics
|
||||
type Job struct {
|
||||
id string
|
||||
jobFunc func()
|
||||
|
@ -18,10 +21,14 @@ type Job struct {
|
|||
mx sync.RWMutex
|
||||
}
|
||||
|
||||
//State Return Job current state.
|
||||
func (j *Job) State() State {
|
||||
j.mx.RLock()
|
||||
defer j.mx.RUnlock()
|
||||
return j.state
|
||||
}
|
||||
|
||||
//NewJobWithID Create new Job with the supplied Id.
|
||||
func NewJobWithID(id string, jobFunc func()) *Job {
|
||||
return &Job{
|
||||
id: id,
|
||||
|
@ -33,14 +40,18 @@ func NewJobWithID(id string, jobFunc func()) *Job {
|
|||
}
|
||||
}
|
||||
|
||||
//NewJob Create new Job, ID is assigned a UUID instead.
|
||||
func NewJob(jobFunc func()) *Job {
|
||||
return NewJobWithID(uuid.New().String(), jobFunc)
|
||||
}
|
||||
|
||||
//ID Return Job ID
|
||||
func (j *Job) ID() string {
|
||||
return j.id
|
||||
}
|
||||
|
||||
//ActualElapsed Return the actual time of procession of Job.
|
||||
// Return -1 if job hasn't started yet.
|
||||
func (j *Job) ActualElapsed() time.Duration {
|
||||
j.mx.RLock()
|
||||
defer j.mx.RUnlock()
|
||||
|
@ -54,6 +65,8 @@ func (j *Job) ActualElapsed() time.Duration {
|
|||
return -1
|
||||
}
|
||||
|
||||
//TotalElapsed Returns the total time between creation of object and finishing processing its job.
|
||||
// Return -1 if job hasn't started yet.
|
||||
func (j *Job) TotalElapsed() time.Duration {
|
||||
j.mx.RLock()
|
||||
defer j.mx.RUnlock()
|
||||
|
@ -66,6 +79,8 @@ func (j *Job) TotalElapsed() time.Duration {
|
|||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
//Run Run the internal Job (synchronous)
|
||||
func (j *Job) Run() error {
|
||||
return j.run()
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
package job
|
||||
|
||||
//State Indicate the state of the Job
|
||||
type State int64
|
||||
|
||||
const (
|
||||
// NEW Job has just been created and hasn't started yet
|
||||
NEW State = iota
|
||||
// RUNNING Job started and is running.
|
||||
RUNNING
|
||||
// FINISHED Job started and finished processing.
|
||||
FINISHED
|
||||
// PANICKED Job started and finished but encountered a panic.
|
||||
PANICKED
|
||||
)
|
||||
|
||||
|
|
2
log.go
2
log.go
|
@ -30,6 +30,7 @@ func (l logger) Named(name string) Logger {
|
|||
return logger{SugaredLogger: l.SugaredLogger.Named(name)}
|
||||
}
|
||||
|
||||
//DefaultLogger Return Default Sched Logger based on Zap's sugared logger
|
||||
func DefaultLogger() Logger {
|
||||
// TODO control verbosity
|
||||
loggerBase, _ := zap.NewDevelopment()
|
||||
|
@ -39,6 +40,7 @@ func DefaultLogger() Logger {
|
|||
}
|
||||
}
|
||||
|
||||
//NopLogger Return a No Op Logger that prints nothing.
|
||||
func NopLogger() Logger {
|
||||
loggerBase := zap.NewNop()
|
||||
sugarLogger := loggerBase.Sugar()
|
||||
|
|
|
@ -25,6 +25,8 @@ func defaultOptions() *options {
|
|||
}
|
||||
}
|
||||
|
||||
// Option to customize schedule behavior, check the sched.With*() functions that implement Option interface for the
|
||||
// available options
|
||||
type Option interface {
|
||||
apply(*options)
|
||||
}
|
||||
|
@ -37,6 +39,7 @@ func (l loggerOption) apply(opts *options) {
|
|||
opts.logger = l.Logger.Named("sched")
|
||||
}
|
||||
|
||||
//WithLogger Use the supplied Logger as the logger.
|
||||
func WithLogger(logger Logger) Option {
|
||||
return loggerOption{Logger: logger}
|
||||
}
|
||||
|
@ -56,10 +59,16 @@ func (m metricsOption) apply(opts *options) {
|
|||
opts.defaultScopePrintEvery = m.defaultScopePrintEvery
|
||||
}
|
||||
|
||||
// WithMetrics Supply a tally.Scope to expose schedule metrics with. Ex. uber-go/tally/prometheus scope to expose
|
||||
// schedule metrics via Prometheus endpoint.
|
||||
// Use WithConsoleMetrics() to supply a predefined metrics console reporter without the need to implement any
|
||||
// special metrics reporter scope.
|
||||
func WithMetrics(metricsScope tally.Scope) Option {
|
||||
return metricsOption{metricsScope: metricsScope, initConsoleMetrics: false, defaultScopePrintEvery: 0}
|
||||
}
|
||||
|
||||
// WithConsoleMetrics a predefined console metrics reporter, uses the Logger interface of the schedule to print out
|
||||
// metrics logs.
|
||||
func WithConsoleMetrics(printEvery time.Duration) Option {
|
||||
return metricsOption{metricsScope: nil, initConsoleMetrics: true, defaultScopePrintEvery: printEvery}
|
||||
}
|
||||
|
|
23
schedule.go
23
schedule.go
|
@ -8,6 +8,8 @@ import (
|
|||
"github.com/uber-go/tally"
|
||||
)
|
||||
|
||||
// Schedule A Schedule is an object that wraps a Job (func(){}) and runs it on a schedule according to the supplied
|
||||
// Timer; With the the ability to expose metrics, and write logs to indicate job health, state, and stats.
|
||||
type Schedule struct {
|
||||
ID string
|
||||
|
||||
|
@ -39,7 +41,7 @@ type Schedule struct {
|
|||
metrics metrics
|
||||
}
|
||||
|
||||
// NewSchedule NewSchedule
|
||||
// NewSchedule Create a new schedule for` jobFunc func()` that will run according to `timer Timer` with the supplied []Options
|
||||
func NewSchedule(id string, timer Timer, jobFunc func(), opts ...Option) *Schedule {
|
||||
var options = defaultOptions()
|
||||
|
||||
|
@ -71,6 +73,12 @@ func NewSchedule(id string, timer Timer, jobFunc func(), opts ...Option) *Schedu
|
|||
}
|
||||
}
|
||||
|
||||
// Start Start the scheduler. Method is concurrent safe. Calling Start() have the following effects according to the
|
||||
// scheduler state:
|
||||
// 1. NEW: Start the Schedule; running the defined Job on the first Timer's Next() time.
|
||||
// 2. STARTED: No Effect (and prints warning)
|
||||
// 3. STOPPED: Restart the schedule
|
||||
// 4. FINISHED: No Effect (and prints warning)
|
||||
func (s *Schedule) Start() {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
|
@ -96,11 +104,19 @@ func (s *Schedule) Start() {
|
|||
go func() {}()
|
||||
}
|
||||
|
||||
// Stop stops the scheduler. Method is **Blocking** and concurrent safe. When called:
|
||||
// 1. Schedule will cancel all waiting scheduled jobs.
|
||||
// 2. Schedule will wait for all running jobs to finish.
|
||||
// Calling Stop() has the following effects depending on the state of the schedule:
|
||||
// 1. NEW: No Effect
|
||||
// 2. STARTED: Stop Schedule
|
||||
// 3. STOPPED: No Effect
|
||||
// 4. FINISHED: No Effect
|
||||
func (s *Schedule) Stop() {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
|
||||
if s.state == STOPPED || s.state == FINISHED {
|
||||
if s.state == STOPPED || s.state == FINISHED || s.state == NEW {
|
||||
return
|
||||
}
|
||||
s.state = STOPPING
|
||||
|
@ -119,6 +135,9 @@ func (s *Schedule) Stop() {
|
|||
_ = s.logger.Sync()
|
||||
}
|
||||
|
||||
// Finish stops the scheduler and put it FINISHED state so that schedule cannot re-start again. Finish() is called
|
||||
// automatically if Schedule Timer returned `done bool` == true.
|
||||
// Method is **Blocking** and concurrent safe.
|
||||
func (s *Schedule) Finish() {
|
||||
// Stop First
|
||||
s.Stop()
|
||||
|
|
16
scheduler.go
16
scheduler.go
|
@ -5,12 +5,15 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
// Scheduler manage one or more Schedule creating them using common options, enforcing unique IDs, and supply methods to
|
||||
// Start / Stop all schedule(s).
|
||||
type Scheduler struct {
|
||||
schedules map[string]*Schedule
|
||||
scheduleOpts []Option
|
||||
mx sync.RWMutex
|
||||
}
|
||||
|
||||
//NewScheduler Creates new Scheduler, opt Options are applied to *every* schedule added and created by this scheduler.
|
||||
func NewScheduler(opts ...Option) *Scheduler {
|
||||
return &Scheduler{
|
||||
schedules: make(map[string]*Schedule),
|
||||
|
@ -18,17 +21,25 @@ func NewScheduler(opts ...Option) *Scheduler {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Scheduler) Add(id string, timer Timer, job func()) {
|
||||
//Add Create a new schedule for` jobFunc func()` that will run according to `timer Timer` with the []Options of the Scheduler.
|
||||
func (s *Scheduler) Add(id string, timer Timer, job func()) error {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
|
||||
if _, ok := s.schedules[id]; !ok {
|
||||
return fmt.Errorf("job with this ID already exists")
|
||||
}
|
||||
|
||||
// Create schedule
|
||||
schedule := NewSchedule(id, timer, job, s.scheduleOpts...)
|
||||
|
||||
// Add to managed schedules
|
||||
s.schedules[id] = schedule
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Start Start the Schedule with the given ID. Return error if no Schedule with the given ID exist.
|
||||
func (s *Scheduler) Start(id string) error {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
|
@ -45,6 +56,7 @@ func (s *Scheduler) Start(id string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
//StartAll Start All Schedules managed by the Scheduler
|
||||
func (s *Scheduler) StartAll() {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
|
@ -53,6 +65,7 @@ func (s *Scheduler) StartAll() {
|
|||
}
|
||||
}
|
||||
|
||||
//Stop Stop the Schedule with the given ID. Return error if no Schedule with the given ID exist.
|
||||
func (s *Scheduler) Stop(id string) error {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
|
@ -64,6 +77,7 @@ func (s *Scheduler) Stop(id string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
//StopAll Stops All Schedules managed by the Scheduler concurrently, but will block until ALL of them have stopped.
|
||||
func (s *Scheduler) StopAll() {
|
||||
s.mx.Lock()
|
||||
defer s.mx.Unlock()
|
||||
|
|
10
state.go
10
state.go
|
@ -1,12 +1,22 @@
|
|||
package sched
|
||||
|
||||
//State Indicate the state of the Schedule
|
||||
type State int64
|
||||
|
||||
const (
|
||||
//NEW Schedule has just been created and hasn't started before
|
||||
NEW State = iota
|
||||
|
||||
// STARTED Start Schedule has started and is running.
|
||||
STARTED
|
||||
|
||||
// STOPPING Schedule is Stopping and is waiting for all active jobs to finish.
|
||||
STOPPING
|
||||
|
||||
// STOPPED Schedule has stopped and no longer scheduling new Jobs.
|
||||
STOPPED
|
||||
|
||||
// FINISHED Schedule has finished, and will not be able to start again.
|
||||
FINISHED
|
||||
)
|
||||
|
||||
|
|
26
timer.go
26
timer.go
|
@ -7,24 +7,33 @@ import (
|
|||
"github.com/gorhill/cronexpr"
|
||||
)
|
||||
|
||||
//Timer is an Interface for a Timer object that is used by a Schedule to determine when to run the next run of a job.
|
||||
// Timer need to implement the Next() method returning the time of the next Job run. Timer indicates that no jobs shall
|
||||
// be scheduled anymore by returning done == true. The `next time.Time` returned with `done bool` == true IS IGNORED.
|
||||
// Next() shall not return time in the past. Time in the past is reset to time.Now() at evaluation time in the scheduler.
|
||||
type Timer interface {
|
||||
Next() (next time.Time, done bool)
|
||||
}
|
||||
|
||||
//Once A timer that run ONCE after an optional specific delay.
|
||||
type Once struct {
|
||||
delay time.Duration
|
||||
done bool
|
||||
}
|
||||
|
||||
func NewOnce(delay time.Duration) (*Once, error) {
|
||||
if delay < 0 {
|
||||
return nil, fmt.Errorf("invalid delay, must be >= 0")
|
||||
//NewOnce Return a timer that trigger ONCE after `d` delay as soon as Timer is inquired for the next Run.
|
||||
//Delay = 0 means the Timer return now(), aka as soon as time is inquired.
|
||||
func NewOnce(d time.Duration) (*Once, error) {
|
||||
if d < 0 {
|
||||
return nil, fmt.Errorf("invalid d, must be >= 0")
|
||||
}
|
||||
return &Once{
|
||||
delay: delay,
|
||||
delay: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewOnceTime Return a timer that trigger ONCE at `t` time.Time.
|
||||
//If `t` is in the past at inquery time, timer will NOT run.
|
||||
func NewOnceTime(t time.Time) (*Once, error) {
|
||||
remaining := time.Until(t)
|
||||
if remaining < 0 {
|
||||
|
@ -38,6 +47,7 @@ func NewOnceTime(t time.Time) (*Once, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
//Next Return Next Time OR a boolean indicating no more Next()(s)
|
||||
func (o *Once) Next() (time.Time, bool) {
|
||||
if !o.done {
|
||||
o.done = true
|
||||
|
@ -46,11 +56,13 @@ func (o *Once) Next() (time.Time, bool) {
|
|||
return time.Time{}, o.done
|
||||
}
|
||||
|
||||
//Fixed A Timer that fires at a fixed duration intervals
|
||||
type Fixed struct {
|
||||
duration time.Duration
|
||||
next time.Time
|
||||
}
|
||||
|
||||
//NewFixed Returns Fixed Timer; A Timer that fires at a fixed duration intervals.
|
||||
func NewFixed(duration time.Duration) (*Fixed, error) {
|
||||
if duration < 0 {
|
||||
return nil, fmt.Errorf("invalid duration, must be >= 0")
|
||||
|
@ -61,6 +73,7 @@ func NewFixed(duration time.Duration) (*Fixed, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
//Next Return Next fire time.
|
||||
func (f *Fixed) Next() (time.Time, bool) {
|
||||
now := time.Now()
|
||||
if now.After(f.next) {
|
||||
|
@ -69,10 +82,14 @@ func (f *Fixed) Next() (time.Time, bool) {
|
|||
return f.next, false
|
||||
}
|
||||
|
||||
//Cron A Timer that fires at according to a cron expression.
|
||||
//All expresion supported by `https://github.com/gorhill/cronexpr` are supported.
|
||||
type Cron struct {
|
||||
expression cronexpr.Expression
|
||||
}
|
||||
|
||||
//NewCron returns a Timer that fires at according to a cron expression.
|
||||
//All expresion supported by `https://github.com/gorhill/cronexpr` are supported.
|
||||
func NewCron(cronExpression string) (*Cron, error) {
|
||||
expression, err := cronexpr.Parse(cronExpression)
|
||||
if err != nil {
|
||||
|
@ -81,6 +98,7 @@ func NewCron(cronExpression string) (*Cron, error) {
|
|||
return &Cron{expression: *expression}, nil
|
||||
}
|
||||
|
||||
//Next Return Next fire time.
|
||||
func (c *Cron) Next() (time.Time, bool) {
|
||||
return c.expression.Next(time.Now()), false
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue