Skip to content

Commit

Permalink
pglock: enforce releasing the lock before stopping heartbeats
Browse files Browse the repository at this point in the history
Closes #36
  • Loading branch information
ucirello committed Feb 20, 2023
1 parent 19fd75b commit a08aaff
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
10 changes: 9 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,11 @@ func (c *Client) Do(ctx context.Context, name string, f func(context.Context, *L
return err
}
defer l.Close()
defer l.heartbeatCancel()
go func() {
// In the hierarchy of context cancelations, it might be the
// case that the heartbeat context has been canceled, even
// though the parent is still intact. This trap will bubble
// children cancellations up.
<-l.heartbeatContext.Done()
cancel()
}()
Expand Down Expand Up @@ -373,6 +376,11 @@ func (c *Client) SendHeartbeat(ctx context.Context, l *Lock) error {
func (c *Client) storeHeartbeat(ctx context.Context, l *Lock) error {
l.mu.Lock()
defer l.mu.Unlock()

if l.isReleased {
return ErrLockAlreadyReleased
}

ctx, cancel := context.WithTimeout(ctx, l.leaseDuration)
defer cancel()

Expand Down
10 changes: 8 additions & 2 deletions lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,15 @@ func (l *Lock) Data() []byte {
return l.data
}

// Close releases the lock.
// Close releases the lock and interrupts the locks heartbeat, if configured.
func (l *Lock) Close() error {
return l.client.Release(l)
// The lock release and the heartbeat may collide. If the heartbeat
// context is canceled during the lock release, the system will rely on
// the elapsed lease duration to make progress. By releasing the lock
// first, it won't matter whether it skips the heartbeat check or not.
err := l.client.Release(l)
l.heartbeatCancel()
return err
}

// IsReleased indicates whether the lock is either released or lost after
Expand Down

0 comments on commit a08aaff

Please sign in to comment.