-
Notifications
You must be signed in to change notification settings - Fork 36
Conversation
* type name will be used as lock.LockOptions by other packages, and that stutters; consider calling this Options (golint) * feature RunWithLock * add go 1.9.2 * coveralls * 🤦 i must read before insert * fix from http://docs.coveralls.io/go * we must do it once * improve caching
* fix linter `collides with package name` * disable coveralls (not work in PR)
.travis.yml
Outdated
go: | ||
- 1.6.4 | ||
- 1.7.5 | ||
- 1.8 | ||
- 1.9.2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be simplified to 1.9.x
for 1.9 branch(1.8.x
etc)
lock.go
Outdated
|
||
if l.opts.RetriesCount > 0 && retries <= 0 { | ||
break | ||
} else if l.opts.RetriesCount > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else
is not needed ;)
lock_test.go
Outdated
@@ -197,6 +218,93 @@ var _ = Describe("Lock", func() { | |||
Expect(res).To(Equal(int32(1))) | |||
}) | |||
|
|||
It("should run with locks and prevent fuzzing", func() { | |||
res := int32(0) | |||
wg := new(sync.WaitGroup) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK var wg sync.WaitGroup
is more preferred style.
lock_test.go
Outdated
if err != nil { | ||
atomic.AddInt32(&res, 100) | ||
return | ||
} else if !ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else
is not needed or ok, err := lock.Lock()
can be moved to if-statement.
lock_test.go
Outdated
res++ | ||
return nil | ||
}, &Options{RetriesCount: count}) | ||
wg.Done() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be deferred?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, this will fail tests
@bsm ping 🙂 |
@cristaloleg, @edganiukov, @DmitriyMV thanks for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this. Before I release a new version I would like to incorporate a few additional changes. Could you please address the feedback, I will then also add a little PR on top. Thanks again!
lock.go
Outdated
return nil, err | ||
} else if !ok { | ||
return nil, ErrCanntGetLock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, that's a breaking change, in which case I will need to release a new major version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should I roll back?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, don't worry, just explaining that I need to bump the major version. could you please also mention this in the function comment
lock.go
Outdated
} | ||
|
||
// NewLock creates a new distributed lock on key | ||
func NewLock(client RedisClient, key string, opts *LockOptions) *Lock { | ||
func NewLock(client RedisClient, key string, opts *Options) *Lock { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the new major version, I would like to rename this to just New
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I can do this
lock.go
Outdated
|
||
token string | ||
mutex sync.Mutex | ||
} | ||
|
||
// RunWithLock run some code with Redis Lock | ||
func RunWithLock(client RedisClient, key string, handler Handler, opts *Options) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you pls change this to: func Run(client RedisClient, key string, opts *Options, handler func() error) error
, i.e. rename func name and put the handler at the end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, no problems
lock.go
Outdated
// RedisClient is a minimal client interface | ||
type RedisClient interface { | ||
SetNX(key string, value interface{}, expiration time.Duration) *redis.BoolCmd | ||
Eval(script string, keys []string, args ...interface{}) *redis.Cmd | ||
} | ||
|
||
// Handler is method wrapper | ||
type Handler func() error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is no need for this, handler
can be just inlined
lock.go
Outdated
@@ -13,35 +14,52 @@ import ( | |||
const luaRefresh = `if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("pexpire", KEYS[1], ARGV[2]) else return 0 end` | |||
const luaRelease = `if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end` | |||
|
|||
var ErrCanntGetLock = errors.New("can't get lock") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you pls rename this to ErrCannotGetLock = errors.New("cannot get lock")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm.. no problems
lock.go
Outdated
if opts == nil { | ||
opts = new(LockOptions) | ||
opts = new(Options) | ||
} | ||
return &Lock{client: client, key: key, opts: *opts.normalize()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since you are at it, maybe rename the struct from Lock
to Locker
too?
@dim yep.. im@kulikov.im |
@dim oops, last commit was not included in the merge, can you remerge? |
or rebase master with this changes |
@im-kulikov don't worry, I will fix in my PR. Just one question: how is |
@dim hmm.. not quite. look, if you want to repeat only a certain number of times - it is enough to specify
|
I think that's the bit I don't "get", I don't quite see a use case for:
As a user I may want to limit the time I am willing to wait to get a lock, but do I really care how many calls are made to redis in this time? (although you can even kind-of control that via Sorry, I really feel this is making the API unnecessarily complicated. At the moment, to enable retries, you only need to set |
@im-kulikov pls take a look at #7 |
@dim In fact, nothing is changed. Only added option to specify the number of attempts. |
Sorry, but can you please explain the use case for this? As said ...
|
will be made 3 attempts ≈ 30 ms (WaitRetry(10ms) * RetriesCount(3) = 30ms) |
No, I understand that, but if we go down this route, I would consider removing |
type name will be used as lock.LockOptions by other packages, and that stutters; consider calling this Options (golint)
feature RunWithLock
add go 1.9.2
coveralls
improve caching