Skip to content
This repository has been archived by the owner on Mar 15, 2024. It is now read-only.

Commit

Permalink
Fixes around worker locker
Browse files Browse the repository at this point in the history
- test coverage
- worker by default not required locker (settings)
- there's interface to apply settings for custom locker (redis, etc)

Signed-off-by: Evgeniy Kulikov <[email protected]>
  • Loading branch information
im-kulikov committed Sep 17, 2019
1 parent f8a4933 commit 1028e38
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 8 deletions.
4 changes: 4 additions & 0 deletions workers/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const (
// ErrEmptyWorkers when workers not passed to params
ErrEmptyWorkers = Error("empty workers")

// ErrEmptyLocker when locker required,
// but not passed to params
ErrEmptyLocker = Error("empty locker")

// ErrEmptyJob when worker job is nil
ErrEmptyJob = Error("empty job")
)
Expand Down
21 changes: 19 additions & 2 deletions workers/workers.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type (
Locker worker.Locker `optional:"true"`
}

// LockerSettings creates copy of locker and applies settings
LockerSettings interface {
Apply(key string, v *viper.Viper) (worker.Locker, error)
}

options struct {
Name string
Job worker.Job
Expand Down Expand Up @@ -103,8 +108,20 @@ func workerByConfig(opts options) (*worker.Worker, error) {
if opts.Viper.IsSet(key + ".immediately") {
w = w.SetImmediately(opts.Viper.GetBool(key + ".immediately"))
}
if opts.Locker != nil {
w = w.WithLock(opts.Locker)

if opts.Viper.IsSet(key + ".lock") {
if opts.Locker == nil {
return nil, errors.Wrap(ErrEmptyLocker, key)
} else if l, ok := opts.Locker.(LockerSettings); ok {
locker, err := l.Apply(key, opts.Viper)
if err != nil {
return nil, err
}

w = w.WithLock(locker)
} else {
w = w.WithLock(opts.Locker)
}
}

return w, nil
Expand Down
92 changes: 86 additions & 6 deletions workers/workers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ import (
"github.com/stretchr/testify/require"
)

type config = map[string]interface{}
type (
config = map[string]interface{}

testLocker struct{ locked int32 }
customLocker struct{ testLocker }
)

const errFailToApplyLockerSettings = Error("fail to apply locker settings")

func mockedViper(cfg config) *viper.Viper {
v := viper.New()
Expand All @@ -28,18 +35,21 @@ func mockedViper(cfg config) *viper.Viper {
return v
}

type customLocker struct {
locked int32
func (c *customLocker) Apply(key string, v *viper.Viper) (worker.Locker, error) {
if v.GetBool(key + ".lock.fail") {
return c, errFailToApplyLockerSettings
}
return c, nil
}

func (c *customLocker) Lock() error {
func (c *testLocker) Lock() error {
if atomic.CompareAndSwapInt32(&c.locked, 0, 1) {
return nil
}
return errors.New("locked")
}

func (c *customLocker) Unlock() {
func (c *testLocker) Unlock() {
atomic.StoreInt32(&c.locked, 0)
}

Expand Down Expand Up @@ -135,7 +145,26 @@ func Test_workerByConfig(t *testing.T) {
Viper: mockedViper(config{}),
}},

{name: "good case",
{
name: "missing locker",
err: ErrEmptyLocker,
args: options{
Name: "test",
Job: nopJob,
Viper: mockedViper(config{
"disabled": false,
"timer": time.Millisecond,
"ticker": time.Millisecond,
"cron": "0 1 * * * *",
"immediately": true,
"lock": true,
}),
},
},

{
name: "error when apply locker settings",
err: errFailToApplyLockerSettings,
args: options{
Name: "test",
Job: nopJob,
Expand All @@ -146,6 +175,57 @@ func Test_workerByConfig(t *testing.T) {
"ticker": time.Millisecond,
"cron": "0 1 * * * *",
"immediately": true,
"lock": true,
"lock.fail": true,
}),
},
},

{
name: "good case",
args: options{
Name: "test",
Job: nopJob,
Viper: mockedViper(config{
"disabled": false,
"timer": time.Millisecond,
"ticker": time.Millisecond,
"cron": "0 1 * * * *",
"immediately": true,
}),
},
},

{
name: "good case with custom locker",
args: options{
Name: "test",
Job: nopJob,
Locker: &customLocker{},
Viper: mockedViper(config{
"disabled": false,
"timer": time.Millisecond,
"ticker": time.Millisecond,
"cron": "0 1 * * * *",
"immediately": true,
"lock": true,
}),
},
},

{
name: "good case with simple locker",
args: options{
Name: "test",
Job: nopJob,
Locker: &testLocker{},
Viper: mockedViper(config{
"disabled": false,
"timer": time.Millisecond,
"ticker": time.Millisecond,
"cron": "0 1 * * * *",
"immediately": true,
"lock": true,
}),
},
},
Expand Down

0 comments on commit 1028e38

Please sign in to comment.