75 lines
1.7 KiB
Go
75 lines
1.7 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"git.myservermanager.com/varakh/upda/util"
|
|
"go.uber.org/zap"
|
|
"time"
|
|
)
|
|
|
|
type lockMemService struct {
|
|
registry *util.InMemoryLockRegistry
|
|
}
|
|
|
|
var (
|
|
errLockMemNotReleased = newServiceError(Conflict, errors.New("lock service: could not release lock"))
|
|
)
|
|
|
|
func newLockMemService() lockService {
|
|
zap.L().Info("Initializing in-memory locking service")
|
|
return &lockMemService{registry: util.NewInMemoryLockRegistry()}
|
|
}
|
|
|
|
// lock locks a given resource without any options (default expiration)
|
|
func (s *lockMemService) lock(ctx context.Context, resource string) (appLock, error) {
|
|
return s.lockWithOptions(ctx, resource, withAppLockOptionExpiry(0))
|
|
}
|
|
|
|
// lockWithOptions locks a given resource, only TTL as option is supported
|
|
func (s *lockMemService) lockWithOptions(ctx context.Context, resource string, options ...appLockOption) (appLock, error) {
|
|
if resource == "" {
|
|
return nil, errorValidationNotBlank
|
|
}
|
|
|
|
var expiration time.Duration = 0
|
|
if options != nil {
|
|
lockOptions := &appLockOptions{}
|
|
for _, o := range options {
|
|
o.apply(lockOptions)
|
|
}
|
|
|
|
if lockOptions.expiry != nil {
|
|
expiration = *lockOptions.expiry
|
|
}
|
|
}
|
|
|
|
zap.L().Sugar().Debugf("Trying to lock '%s'", resource)
|
|
|
|
s.registry.LockWithTTL(resource, expiration)
|
|
|
|
zap.L().Sugar().Debugf("Locked '%s'", resource)
|
|
|
|
l := &inMemoryLock{
|
|
registry: s.registry,
|
|
resource: resource,
|
|
}
|
|
|
|
return l, nil
|
|
}
|
|
|
|
var _ appLock = (*inMemoryLock)(nil)
|
|
|
|
type inMemoryLock struct {
|
|
registry *util.InMemoryLockRegistry
|
|
resource string
|
|
}
|
|
|
|
func (r inMemoryLock) unlock(ctx context.Context) error {
|
|
zap.L().Sugar().Debugf("Unlocking '%s'", r.resource)
|
|
|
|
if err := r.registry.Unlock(r.resource); err != nil {
|
|
return errLockMemNotReleased
|
|
}
|
|
return nil
|
|
}
|