upda/server/service_lock_mem.go
Varakh 165b992629
All checks were successful
/ build (push) Successful in 3m11s
feature(locking): add proper locking and overhaul existing locking service (#34)
Reviewed-on: #34
Co-authored-by: Varakh <varakh@varakh.de>
Co-committed-by: Varakh <varakh@varakh.de>
2024-05-24 00:54:35 +02:00

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("Initialized 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
}