Update docs, tests, and release prep (#629)

This commit is contained in:
John Roesler 2023-12-11 10:39:59 -06:00 committed by GitHub
parent 5814fbcb6f
commit aa4400d224
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 230 additions and 199 deletions

View File

@ -8,15 +8,6 @@ gocron is a job scheduling package which lets you run Go functions at pre-determ
If you want to chat, you can find us on Slack at
[<img src="https://img.shields.io/badge/gophers-gocron-brightgreen?logo=slack">](https://gophers.slack.com/archives/CQ7T0T1FW)
## Concepts
- **Job**: The encapsulates a "task", which is made up of a go func and any function parameters, and then
provides the scheduler with the time the job should be scheduled to run.
- **Executor**: The executor, calls the "task" function and manages the complexities of different job
execution timing (e.g. singletons that shouldn't overrun each other, limiting the max number of jobs running)
- **Scheduler**: The scheduler keeps track of all the jobs and sends each job to the executor when
it is ready to be run.
## Quick Start
```
@ -70,6 +61,16 @@ func main() {
}
```
## Concepts
- **Job**: The job encapsulates a "task", which is made up of a go function and any function parameters. The Job then
provides the scheduler with the time the job should next be scheduled to run.
- **Scheduler**: The scheduler keeps track of all the jobs and sends each job to the executor when
it is ready to be run.
- **Executor**: The executor calls the job's task and manages the complexities of different job
execution timing requirements (e.g. singletons that shouldn't overrun each other, limiting the max number of jobs running)
## Features
- **Job types**: Jobs can be run at various intervals.
@ -85,7 +86,7 @@ func main() {
Jobs can be run every x weeks on specific days of the week and at specific times.
- [**Monthly**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#MonthlyJob):
Jobs can be run every x months on specific days of the month and at specific times.
- **Limited Concurrency**: Jobs can be limited individually or across the entire scheduler.
- **Concurrency Limits**: Jobs can be limited individually or across the entire scheduler.
- [**Per job limiting with singleton mode**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithSingletonMode):
Jobs can be limited to a single concurrent execution that either reschedules (skips overlapping executions)
or queues (waits for the previous execution to finish).
@ -93,6 +94,7 @@ func main() {
Jobs can be limited to a certain number of concurrent executions across the entire scheduler
using either reschedule (skip when the limit is met) or queue (jobs are added to a queue to
wait for the limit to be available).
- **Note:** A scheduler limit and a job limit can both be enabled.
- **Distributed instances of gocron**: Multiple instances of gocron can be run.
- [**Elector**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithDistributedElector):
An elector can be used to elect a single instance of gocron to run as the primary with the
@ -103,31 +105,33 @@ func main() {
- Implementations: [go-co-op lockers](https://github.com/go-co-op?q=-lock&type=all&language=&sort=)
- **Events**: Job events can trigger actions.
- [**Listeners**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithEventListeners):
[Event listeners](https://pkg.go.dev/github.com/go-co-op/gocron/v2#EventListener)
can be added to a job or all jobs in the
Can be added to a job, with [event listeners](https://pkg.go.dev/github.com/go-co-op/gocron/v2#EventListener),
or all jobs across the
[scheduler](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithGlobalJobOptions)
to listen for job events and trigger actions.
- **Options**: Many job and scheduler options are available
- **Options**: Many job and scheduler options are available.
- [**Job options**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#JobOption):
Job options can be set when creating a job using `NewJob`.
- [**Global job options**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithGlobalJobOptions):
Global job options can be set when creating a scheduler using `NewScheduler`.
Global job options can be set when creating a scheduler using `NewScheduler`
and the `WithGlobalJobOptions` option.
- [**Scheduler options**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#SchedulerOption):
Scheduler options can be set when creating a scheduler using `NewScheduler`.
- **Logging**: Logs can be enabled.
- [Logger](https://pkg.go.dev/github.com/go-co-op/gocron/v2#Logger):
The Logger interface can be implemented with your desired logging library.
The provided NewLogger uses the standard library's log package.
- **Mocking**: The gocron library is set up to enable testing.
- **Testing**: The gocron library is set up to enable testing.
- Mocks are provided in [the mock package](mocks) using [gomock](https://github.com/uber-go/mock).
- Time can be mocked by passing in a [FakeClock](https://pkg.go.dev/github.com/jonboulle/clockwork#FakeClock)
to [WithClock](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithClock) -
see the example on WithClock in the go-docs.
see the [example on WithClock](https://pkg.go.dev/github.com/go-co-op/gocron/v2#example-WithClock).
## Supporters
[Jetbrains](https://www.jetbrains.com/?from=gocron) supports this project with Intellij licenses.
We appreciate their support for free and open source software!
We appreciate the support for free and open source software!
- [Jetbrains](https://www.jetbrains.com/?from=gocron) supports this project with Intellij licenses.
## Star History

View File

@ -1,4 +1,4 @@
//go:generate mockgen -source=distributed.go -destination=mocks/distributed.go -package=gocronmocks
//go:generate mockgen -destination=mocks/distributed.go -package=gocronmocks . Elector,Locker,Lock
package gocron
import (

View File

@ -231,6 +231,13 @@ func (e *executor) limitModeRunner(name string, in chan uuid.UUID, wg *waitGroup
return
case e.jobIDsOut <- j.id:
}
// remove the limiter block to allow another job to be scheduled
if limitMode == LimitModeReschedule {
select {
case <-rescheduleLimiter:
default:
}
}
continue
}
e.limitMode.singletonJobs[id] = struct{}{}

5
go.mod
View File

@ -8,14 +8,13 @@ require (
github.com/robfig/cron/v3 v3.0.1
github.com/stretchr/testify v1.8.4
go.uber.org/goleak v1.3.0
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

12
go.sum
View File

@ -5,12 +5,12 @@ github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
@ -19,10 +19,10 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

2
job.go
View File

@ -1,4 +1,4 @@
//go:generate mockgen -source=job.go -destination=mocks/job.go -package=gocronmocks
//go:generate mockgen -destination=mocks/job.go -package=gocronmocks . Job
package gocron
import (

View File

@ -313,10 +313,9 @@ func TestJob_LastRun(t *testing.T) {
testTime := time.Date(2000, 1, 1, 0, 0, 0, 0, time.Local)
fakeClock := clockwork.NewFakeClockAt(testTime)
s, err := newTestScheduler(
s := newTestScheduler(t,
WithClock(fakeClock),
)
require.NoError(t, err)
j, err := s.NewJob(
DurationJob(

View File

@ -1,4 +1,4 @@
//go:generate mockgen -source=logger.go -destination=mocks/logger.go -package=gocronmocks
//go:generate mockgen -destination=mocks/logger.go -package=gocronmocks . Logger
package gocron
import (

View File

@ -1,9 +1,9 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: distributed.go
// Source: github.com/go-co-op/gocron/v2 (interfaces: Elector,Locker,Lock)
//
// Generated by this command:
//
// mockgen -source=distributed.go -destination=mocks/distributed.go -package=gocronmocks
// mockgen -destination=mocks/distributed.go -package=gocronmocks . Elector,Locker,Lock
//
// Package gocronmocks is a generated GoMock package.
package gocronmocks
@ -12,6 +12,7 @@ import (
context "context"
reflect "reflect"
gocron "github.com/go-co-op/gocron/v2"
gomock "go.uber.org/mock/gomock"
)
@ -51,3 +52,78 @@ func (mr *MockElectorMockRecorder) IsLeader(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsLeader", reflect.TypeOf((*MockElector)(nil).IsLeader), arg0)
}
// MockLocker is a mock of Locker interface.
type MockLocker struct {
ctrl *gomock.Controller
recorder *MockLockerMockRecorder
}
// MockLockerMockRecorder is the mock recorder for MockLocker.
type MockLockerMockRecorder struct {
mock *MockLocker
}
// NewMockLocker creates a new mock instance.
func NewMockLocker(ctrl *gomock.Controller) *MockLocker {
mock := &MockLocker{ctrl: ctrl}
mock.recorder = &MockLockerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockLocker) EXPECT() *MockLockerMockRecorder {
return m.recorder
}
// Lock mocks base method.
func (m *MockLocker) Lock(arg0 context.Context, arg1 string) (gocron.Lock, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Lock", arg0, arg1)
ret0, _ := ret[0].(gocron.Lock)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Lock indicates an expected call of Lock.
func (mr *MockLockerMockRecorder) Lock(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lock", reflect.TypeOf((*MockLocker)(nil).Lock), arg0, arg1)
}
// MockLock is a mock of Lock interface.
type MockLock struct {
ctrl *gomock.Controller
recorder *MockLockMockRecorder
}
// MockLockMockRecorder is the mock recorder for MockLock.
type MockLockMockRecorder struct {
mock *MockLock
}
// NewMockLock creates a new mock instance.
func NewMockLock(ctrl *gomock.Controller) *MockLock {
mock := &MockLock{ctrl: ctrl}
mock.recorder = &MockLockMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockLock) EXPECT() *MockLockMockRecorder {
return m.recorder
}
// Unlock mocks base method.
func (m *MockLock) Unlock(arg0 context.Context) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Unlock", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Unlock indicates an expected call of Unlock.
func (mr *MockLockMockRecorder) Unlock(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unlock", reflect.TypeOf((*MockLock)(nil).Unlock), arg0)
}

View File

@ -3,7 +3,7 @@ module github.com/go-co-op/gocronmocks/v2
go 1.20
require (
github.com/go-co-op/gocron/v2 v2.0.0-rc1
github.com/go-co-op/gocron/v2 v2.0.0-rc4
github.com/google/uuid v1.4.0
go.uber.org/mock v0.3.0
)
@ -11,5 +11,5 @@ require (
require (
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
)

View File

@ -1,6 +1,6 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/go-co-op/gocron/v2 v2.0.0-rc1 h1:qkj0WVO6uh6ibZa2CQ0Ifxk3A+c6rawZnIby94/5sAM=
github.com/go-co-op/gocron/v2 v2.0.0-rc1/go.mod h1:3SLoqKnyORFVN0VvFFb1383hM4WD9XHBPn9aUUp7sQs=
github.com/go-co-op/gocron/v2 v2.0.0-rc4 h1:KFYg2CzyHZwPZL/uNnQKEyeL9oKEUQbiLThArcZaVmw=
github.com/go-co-op/gocron/v2 v2.0.0-rc4/go.mod h1:3SLoqKnyORFVN0VvFFb1383hM4WD9XHBPn9aUUp7sQs=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
@ -12,6 +12,6 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -1,9 +1,9 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: job.go
// Source: github.com/go-co-op/gocron/v2 (interfaces: Job)
//
// Generated by this command:
//
// mockgen -source=job.go -destination=mocks/job.go -package=gocronmocks
// mockgen -destination=mocks/job.go -package=gocronmocks . Job
//
// Package gocronmocks is a generated GoMock package.
package gocronmocks
@ -16,80 +16,6 @@ import (
gomock "go.uber.org/mock/gomock"
)
// MockJobDefinition is a mock of JobDefinition interface.
type MockJobDefinition struct {
ctrl *gomock.Controller
recorder *MockJobDefinitionMockRecorder
}
// MockJobDefinitionMockRecorder is the mock recorder for MockJobDefinition.
type MockJobDefinitionMockRecorder struct {
mock *MockJobDefinition
}
// NewMockJobDefinition creates a new mock instance.
func NewMockJobDefinition(ctrl *gomock.Controller) *MockJobDefinition {
mock := &MockJobDefinition{ctrl: ctrl}
mock.recorder = &MockJobDefinitionMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockJobDefinition) EXPECT() *MockJobDefinitionMockRecorder {
return m.recorder
}
// setup mocks base method.
func (m *MockJobDefinition) setup(arg0 *internalJob, arg1 *time.Location) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "setup", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// setup indicates an expected call of setup.
func (mr *MockJobDefinitionMockRecorder) setup(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "setup", reflect.TypeOf((*MockJobDefinition)(nil).setup), arg0, arg1)
}
// MockjobSchedule is a mock of jobSchedule interface.
type MockjobSchedule struct {
ctrl *gomock.Controller
recorder *MockjobScheduleMockRecorder
}
// MockjobScheduleMockRecorder is the mock recorder for MockjobSchedule.
type MockjobScheduleMockRecorder struct {
mock *MockjobSchedule
}
// NewMockjobSchedule creates a new mock instance.
func NewMockjobSchedule(ctrl *gomock.Controller) *MockjobSchedule {
mock := &MockjobSchedule{ctrl: ctrl}
mock.recorder = &MockjobScheduleMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockjobSchedule) EXPECT() *MockjobScheduleMockRecorder {
return m.recorder
}
// next mocks base method.
func (m *MockjobSchedule) next(lastRun time.Time) time.Time {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "next", lastRun)
ret0, _ := ret[0].(time.Time)
return ret0
}
// next indicates an expected call of next.
func (mr *MockjobScheduleMockRecorder) next(lastRun any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "next", reflect.TypeOf((*MockjobSchedule)(nil).next), lastRun)
}
// MockJob is a mock of Job interface.
type MockJob struct {
ctrl *gomock.Controller

View File

@ -1,9 +1,9 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: logger.go
// Source: github.com/go-co-op/gocron/v2 (interfaces: Logger)
//
// Generated by this command:
//
// mockgen -source=logger.go -destination=mocks/logger.go -package=gocronmocks
// mockgen -destination=mocks/logger.go -package=gocronmocks . Logger
//
// Package gocronmocks is a generated GoMock package.
package gocronmocks
@ -38,69 +38,69 @@ func (m *MockLogger) EXPECT() *MockLoggerMockRecorder {
}
// Debug mocks base method.
func (m *MockLogger) Debug(msg string, args ...any) {
func (m *MockLogger) Debug(arg0 string, arg1 ...any) {
m.ctrl.T.Helper()
varargs := []any{msg}
for _, a := range args {
varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Debug", varargs...)
}
// Debug indicates an expected call of Debug.
func (mr *MockLoggerMockRecorder) Debug(msg any, args ...any) *gomock.Call {
func (mr *MockLoggerMockRecorder) Debug(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{msg}, args...)
varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Debug", reflect.TypeOf((*MockLogger)(nil).Debug), varargs...)
}
// Error mocks base method.
func (m *MockLogger) Error(msg string, args ...any) {
func (m *MockLogger) Error(arg0 string, arg1 ...any) {
m.ctrl.T.Helper()
varargs := []any{msg}
for _, a := range args {
varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Error", varargs...)
}
// Error indicates an expected call of Error.
func (mr *MockLoggerMockRecorder) Error(msg any, args ...any) *gomock.Call {
func (mr *MockLoggerMockRecorder) Error(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{msg}, args...)
varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Error", reflect.TypeOf((*MockLogger)(nil).Error), varargs...)
}
// Info mocks base method.
func (m *MockLogger) Info(msg string, args ...any) {
func (m *MockLogger) Info(arg0 string, arg1 ...any) {
m.ctrl.T.Helper()
varargs := []any{msg}
for _, a := range args {
varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Info", varargs...)
}
// Info indicates an expected call of Info.
func (mr *MockLoggerMockRecorder) Info(msg any, args ...any) *gomock.Call {
func (mr *MockLoggerMockRecorder) Info(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{msg}, args...)
varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockLogger)(nil).Info), varargs...)
}
// Warn mocks base method.
func (m *MockLogger) Warn(msg string, args ...any) {
func (m *MockLogger) Warn(arg0 string, arg1 ...any) {
m.ctrl.T.Helper()
varargs := []any{msg}
for _, a := range args {
varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Warn", varargs...)
}
// Warn indicates an expected call of Warn.
func (mr *MockLoggerMockRecorder) Warn(msg any, args ...any) *gomock.Call {
func (mr *MockLoggerMockRecorder) Warn(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{msg}, args...)
varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warn", reflect.TypeOf((*MockLogger)(nil).Warn), varargs...)
}

View File

@ -1,9 +1,9 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: scheduler.go
// Source: github.com/go-co-op/gocron/v2 (interfaces: Scheduler)
//
// Generated by this command:
//
// mockgen -source=scheduler.go -destination=mocks/scheduler.go -package=gocronmocks
// mockgen -destination=mocks/scheduler.go -package=gocronmocks . Scheduler
//
// Package gocronmocks is a generated GoMock package.
package gocronmocks
@ -11,7 +11,7 @@ package gocronmocks
import (
reflect "reflect"
v2 "github.com/go-co-op/gocron/v2"
gocron "github.com/go-co-op/gocron/v2"
uuid "github.com/google/uuid"
gomock "go.uber.org/mock/gomock"
)
@ -40,10 +40,10 @@ func (m *MockScheduler) EXPECT() *MockSchedulerMockRecorder {
}
// Jobs mocks base method.
func (m *MockScheduler) Jobs() []v2.Job {
func (m *MockScheduler) Jobs() []gocron.Job {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Jobs")
ret0, _ := ret[0].([]v2.Job)
ret0, _ := ret[0].([]gocron.Job)
return ret0
}
@ -54,14 +54,14 @@ func (mr *MockSchedulerMockRecorder) Jobs() *gomock.Call {
}
// NewJob mocks base method.
func (m *MockScheduler) NewJob(arg0 v2.JobDefinition, arg1 v2.Task, arg2 ...v2.JobOption) (v2.Job, error) {
func (m *MockScheduler) NewJob(arg0 gocron.JobDefinition, arg1 gocron.Task, arg2 ...gocron.JobOption) (gocron.Job, error) {
m.ctrl.T.Helper()
varargs := []any{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "NewJob", varargs...)
ret0, _ := ret[0].(v2.Job)
ret0, _ := ret[0].(gocron.Job)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -144,14 +144,14 @@ func (mr *MockSchedulerMockRecorder) StopJobs() *gomock.Call {
}
// Update mocks base method.
func (m *MockScheduler) Update(arg0 uuid.UUID, arg1 v2.JobDefinition, arg2 v2.Task, arg3 ...v2.JobOption) (v2.Job, error) {
func (m *MockScheduler) Update(arg0 uuid.UUID, arg1 gocron.JobDefinition, arg2 gocron.Task, arg3 ...gocron.JobOption) (gocron.Job, error) {
m.ctrl.T.Helper()
varargs := []any{arg0, arg1, arg2}
for _, a := range arg3 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Update", varargs...)
ret0, _ := ret[0].(v2.Job)
ret0, _ := ret[0].(gocron.Job)
ret1, _ := ret[1].(error)
return ret0, ret1
}

View File

@ -1,4 +1,4 @@
//go:generate mockgen -source=scheduler.go -destination=mocks/scheduler.go -package=gocronmocks
//go:generate mockgen -destination=mocks/scheduler.go -package=gocronmocks . Scheduler
package gocron
import (

View File

@ -14,7 +14,7 @@ import (
"go.uber.org/goleak"
)
func newTestScheduler(options ...SchedulerOption) (Scheduler, error) {
func newTestScheduler(t *testing.T, options ...SchedulerOption) Scheduler {
// default test options
out := []SchedulerOption{
WithLogger(NewLogger(LogLevelDebug)),
@ -23,7 +23,9 @@ func newTestScheduler(options ...SchedulerOption) (Scheduler, error) {
// append any additional options 2nd to override defaults if needed
out = append(out, options...)
return NewScheduler(out...)
s, err := NewScheduler(out...)
require.NoError(t, err)
return s
}
func TestScheduler_OneSecond_NoOptions(t *testing.T) {
@ -66,10 +68,9 @@ func TestScheduler_OneSecond_NoOptions(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler()
require.NoError(t, err)
s := newTestScheduler(t)
_, err = s.NewJob(tt.jd, tt.tsk)
_, err := s.NewJob(tt.jd, tt.tsk)
require.NoError(t, err)
s.Start()
@ -147,10 +148,9 @@ func TestScheduler_LongRunningJobs(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler(tt.options...)
require.NoError(t, err)
s := newTestScheduler(t, tt.options...)
_, err = s.NewJob(tt.jd, tt.tsk, tt.opts...)
_, err := s.NewJob(tt.jd, tt.tsk, tt.opts...)
require.NoError(t, err)
s.Start()
@ -217,8 +217,7 @@ func TestScheduler_Update(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler()
require.NoError(t, err)
s := newTestScheduler(t)
j, err := s.NewJob(tt.initialJob, tt.tsk)
require.NoError(t, err)
@ -294,12 +293,11 @@ func TestScheduler_StopTimeout(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
testDoneCtx, cancel := context.WithCancel(context.Background())
s, err := newTestScheduler(
s := newTestScheduler(t,
WithStopTimeout(time.Millisecond*100),
)
require.NoError(t, err)
_, err = s.NewJob(tt.jd, NewTask(tt.f, testDoneCtx), tt.opts...)
_, err := s.NewJob(tt.jd, NewTask(tt.f, testDoneCtx), tt.opts...)
require.NoError(t, err)
s.Start()
@ -316,11 +314,11 @@ func TestScheduler_Shutdown(t *testing.T) {
goleak.VerifyNone(t)
t.Run("start, stop, start, shutdown", func(t *testing.T) {
s, err := newTestScheduler(
s := newTestScheduler(t,
WithStopTimeout(time.Second),
)
require.NoError(t, err)
_, err = s.NewJob(
_, err := s.NewJob(
DurationJob(
50*time.Millisecond,
),
@ -346,10 +344,9 @@ func TestScheduler_Shutdown(t *testing.T) {
})
t.Run("calling Job methods after shutdown errors", func(t *testing.T) {
s, err := newTestScheduler(
s := newTestScheduler(t,
WithStopTimeout(time.Second),
)
require.NoError(t, err)
j, err := s.NewJob(
DurationJob(
100*time.Millisecond,
@ -461,10 +458,9 @@ func TestScheduler_NewJob(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler()
require.NoError(t, err)
s := newTestScheduler(t)
_, err = s.NewJob(tt.jd, tt.tsk, tt.opts...)
_, err := s.NewJob(tt.jd, tt.tsk, tt.opts...)
require.NoError(t, err)
s.Start()
@ -727,23 +723,21 @@ func TestScheduler_NewJobErrors(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler(
s := newTestScheduler(t,
WithStopTimeout(time.Millisecond*50),
)
require.NoError(t, err)
_, err = s.NewJob(tt.jd, NewTask(func() {}), tt.opts...)
_, err := s.NewJob(tt.jd, NewTask(func() {}), tt.opts...)
assert.ErrorIs(t, err, tt.err)
require.NoError(t, s.Shutdown())
})
t.Run(tt.name+" global", func(t *testing.T) {
s, err := newTestScheduler(
s := newTestScheduler(t,
WithStopTimeout(time.Millisecond*50),
WithGlobalJobOptions(tt.opts...),
)
require.NoError(t, err)
_, err = s.NewJob(tt.jd, NewTask(func() {}))
_, err := s.NewJob(tt.jd, NewTask(func() {}))
assert.ErrorIs(t, err, tt.err)
require.NoError(t, s.Shutdown())
})
@ -784,10 +778,9 @@ func TestScheduler_NewJobTask(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler()
require.NoError(t, err)
s := newTestScheduler(t)
_, err = s.NewJob(DurationJob(time.Second), tt.tsk)
_, err := s.NewJob(DurationJob(time.Second), tt.tsk)
assert.ErrorIs(t, err, tt.err)
require.NoError(t, s.Shutdown())
})
@ -845,7 +838,7 @@ func TestScheduler_WithOptionsErrors(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := newTestScheduler(tt.opt)
_, err := NewScheduler(tt.opt)
assert.ErrorIs(t, err, tt.err)
})
}
@ -875,13 +868,12 @@ func TestScheduler_Singleton(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
jobRanCh := make(chan struct{}, 10)
s, err := newTestScheduler(
s := newTestScheduler(t,
WithStopTimeout(1*time.Second),
WithLocation(time.Local),
)
require.NoError(t, err)
_, err = s.NewJob(
_, err := s.NewJob(
DurationJob(
tt.duration,
),
@ -948,16 +940,15 @@ func TestScheduler_LimitMode(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler(
s := newTestScheduler(t,
WithLimitConcurrentJobs(tt.limit, tt.limitMode),
WithStopTimeout(2*time.Second),
)
require.NoError(t, err)
jobRanCh := make(chan struct{}, 20)
for i := 0; i < tt.numJobs; i++ {
_, err = s.NewJob(
_, err := s.NewJob(
DurationJob(tt.duration),
NewTask(func() {
time.Sleep(tt.duration / 2)
@ -1024,17 +1015,16 @@ func TestScheduler_LimitModeAndSingleton(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler(
s := newTestScheduler(t,
WithLimitConcurrentJobs(tt.limit, tt.limitMode),
WithStopTimeout(2*time.Second),
)
require.NoError(t, err)
jobRanCh := make(chan int, 20)
for i := 0; i < tt.numJobs; i++ {
jobNum := i
_, err = s.NewJob(
_, err := s.NewJob(
DurationJob(tt.duration),
NewTask(func() {
time.Sleep(tt.duration / 2)
@ -1149,15 +1139,14 @@ func TestScheduler_WithDistributed(t *testing.T) {
schedulersDone := make(chan struct{}, tt.count)
for i := tt.count; i > 0; i-- {
s, err := newTestScheduler(
s := newTestScheduler(t,
tt.opt,
)
require.NoError(t, err)
go func() {
s.Start()
_, err = s.NewJob(
_, err := s.NewJob(
DurationJob(
time.Second,
),
@ -1229,8 +1218,7 @@ func TestScheduler_RemoveJob(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler()
require.NoError(t, err)
s := newTestScheduler(t)
var id uuid.UUID
if tt.addJob {
@ -1242,7 +1230,7 @@ func TestScheduler_RemoveJob(t *testing.T) {
}
time.Sleep(50 * time.Millisecond)
err = s.RemoveJob(id)
err := s.RemoveJob(id)
assert.ErrorIs(t, err, err)
require.NoError(t, s.Shutdown())
})
@ -1310,9 +1298,8 @@ func TestScheduler_WithEventListeners(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := newTestScheduler()
require.NoError(t, err)
_, err = s.NewJob(
s := newTestScheduler(t)
_, err := s.NewJob(
DurationJob(time.Minute*10),
tt.tsk,
WithStartAt(
@ -1343,3 +1330,36 @@ func TestScheduler_WithEventListeners(t *testing.T) {
})
}
}
func TestScheduler_ManyJobs(t *testing.T) {
s := newTestScheduler(t)
jobsRan := make(chan struct{}, 20000)
for i := 1; i <= 1000; i++ {
_, err := s.NewJob(
DurationJob(
time.Millisecond*100,
),
NewTask(
func() {
jobsRan <- struct{}{}
},
),
WithStartAt(WithStartImmediately()),
)
require.NoError(t, err)
}
s.Start()
time.Sleep(1 * time.Second)
require.NoError(t, s.Shutdown())
close(jobsRan)
var count int
for range jobsRan {
count++
}
assert.GreaterOrEqual(t, count, 9900)
assert.LessOrEqual(t, count, 11000)
}