mirror of
https://github.com/ente-io/ente.git
synced 2025-05-05 12:57:34 +00:00
67 lines
2.0 KiB
Go
67 lines
2.0 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)
|
|
}
|