ente/server/pkg/controller/lock/lock.go

67 lines
2 KiB
Go

package lock
import (
"fmt"
"github.com/ente-io/museum/pkg/repo"
"github.com/ente-io/stacktrace"
log "github.com/sirupsen/logrus"
)
// LockController exposes functions to obtain locks before entering critical sections
type LockController struct {
TaskLockingRepo *repo.TaskLockRepository
HostName string
}
// Try to obtain a lock with the given lockID.
//
// Return false if the lock is already taken.
//
// A call to this function should be matched by a call to ReleaseLock. A common
// pattern is to put the ReleaseLock into a defer statement immediately
// following the lock acquisition.
//
// However, it is also fine to omit the release. Such would be useful for cases
// where we want to ensure the same job cannot run again until the expiry time
// is past.
func (c *LockController) TryLock(lockID string, lockUntil int64) bool {
lockStatus, err := c.TaskLockingRepo.AcquireLock(lockID, lockUntil, c.HostName)
if err != nil || !lockStatus {
return false
}
return true
}
// ExtendLock refreshes an existing lock by updating its locked_at to now and
// extending its lockUntil.
//
// It is only valid to call this method when holding an existing lock previously
// obtained using TryLock.
func (c *LockController) ExtendLock(lockID string, lockUntil int64) error {
foundLock, err := c.TaskLockingRepo.ExtendLock(lockID, lockUntil, c.HostName)
if err != nil {
return stacktrace.Propagate(err, "Unable to extend lock %v", lockID)
}
if !foundLock {
return fmt.Errorf("no existing lock for %v", lockID)
}
return nil
}
// Release a lock that was obtained earlier using TryLock.
func (c *LockController) ReleaseLock(lockID string) {
err := c.TaskLockingRepo.ReleaseLock(lockID)
if err != nil {
log.Errorf("Error while releasing lock %v: %s", lockID, err)
}
}
func (c *LockController) ReleaseHostLock() {
count, err := c.TaskLockingRepo.ReleaseLocksBy(c.HostName)
if err != nil {
log.Errorf("Error while releasing host lock: %s", err)
}
log.Infof("Released %d locks held by %s", *count, c.HostName)
}