Skip to content

Commit

Permalink
Merge pull request #13 from gochore/dev
Browse files Browse the repository at this point in the history
support NewJobWithNonAnonymousFunc

close #14
  • Loading branch information
wolfogre authored Mar 3, 2020
2 parents 4f76a71 + 825c5d5 commit a029768
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 1 deletion.
4 changes: 4 additions & 0 deletions cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func (c *Cron) AddJobs(jobs ...Job) error {
}

func (c *Cron) addJob(job Job) error {
if job.Key() == "" {
return errors.New("empty key")
}

for _, j := range c.jobs {
if j.key == job.Key() {
return errors.New("added already")
Expand Down
12 changes: 12 additions & 0 deletions cron_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ func TestCron_AddJobs(t *testing.T) {
},
wantErr: true,
},
{
name: "empty key",
fields: fields{
cron: c,
},
args: args{
jobs: []Job{
NewJob("", "* * * * * *", nil),
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
33 changes: 32 additions & 1 deletion job.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package dcron

import "context"
import (
"context"
"reflect"
"regexp"
"runtime"
"strings"
)

type JobMeta interface {
Key() string
Expand Down Expand Up @@ -29,6 +35,18 @@ func NewJob(key, spec string, run RunFunc, options ...JobOption) Job {
}
}

// NewJobWithNonAnonymousFunc return a new Job with the 'run' function's name as key.
// Be careful, the 'run' should be a non-anonymous function,
// or returned Job will has a emtpy key, and can not be added to a Cron.
func NewJobWithNonAnonymousFunc(spec string, run RunFunc, options ...JobOption) Job {
return &wrappedJob{
key: funcName(run),
spec: spec,
run: run,
options: options,
}
}

func (j *wrappedJob) Key() string {
return j.key
}
Expand All @@ -47,3 +65,16 @@ func (j *wrappedJob) Run(ctx context.Context) error {
func (j *wrappedJob) Options() []JobOption {
return j.options
}

func funcName(run RunFunc) string {
if run != nil {
name := runtime.FuncForPC(reflect.ValueOf(run).Pointer()).Name()
splits := strings.Split(name, ".")
name = strings.TrimSuffix(splits[len(splits)-1], "-fm") // method closures have a "-fm" suffix
if regexp.MustCompile("^func[0-9]+$").MatchString(name) {
return ""
}
return name
}
return ""
}
77 changes: 77 additions & 0 deletions job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,80 @@ func Test_wrappedJob_Spec(t *testing.T) {
})
}
}

func TestNewJobWithNonAnonymousFunc(t *testing.T) {
type args struct {
spec string
run RunFunc
options []JobOption
}
tests := []struct {
name string
args args
check func(t *testing.T, job Job)
}{
{
name: "regular",
args: args{
run: Func,
},
check: func(t *testing.T, job Job) {
if job.Key() != "Func" {
t.Fatal(job.Key())
}
},
},
{
name: "method",
args: args{
run: Foo{}.Method,
},
check: func(t *testing.T, job Job) {
if job.Key() != "Method" {
t.Fatal(job.Key())
}
},
},
{
name: "nil",
args: args{
run: nil,
},
check: func(t *testing.T, job Job) {
if job.Key() != "" {
t.Fatal(job.Key())
}
},
},
{
name: "anonymous func",
args: args{
run: func(ctx context.Context) error {
return nil
},
},
check: func(t *testing.T, job Job) {
if job.Key() != "" {
t.Fatal(job.Key())
}
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := NewJobWithNonAnonymousFunc(tt.args.spec, tt.args.run, tt.args.options...)
tt.check(t, got)
})
}
}

func Func(ctx context.Context) error {
return nil
}

type Foo struct {
}

func (Foo) Method(ctx context.Context) error {
return nil
}

0 comments on commit a029768

Please sign in to comment.