package server import ( "context" "math" "time" ) // lockService provides methods for locking resources, behavior depends on underlying implementation type lockService interface { // lock locks a resource applying default TTL values (no options for in-memory locking, otherwise applies default implementation of other lockers) lock(ctx context.Context, resource string) (appLock, error) // lockWithOptions locks a resource with given options, has no effect for in-memory locking lockWithOptions(ctx context.Context, resource string, options ...appLockOption) (appLock, error) } type appLock interface { // unlock unlocks a lock unlock(ctx context.Context) error } type appLockOption interface { Apply(l *appLockOptions) } type appLockOptionFunc func(o *appLockOptions) func (f appLockOptionFunc) Apply(o *appLockOptions) { f(o) } type appLockOptions struct { ttl *time.Duration retryDelay *time.Duration maxRetries *int } func withAppLockOptionExpiry(expiry time.Duration) appLockOption { return appLockOptionFunc(func(o *appLockOptions) { o.ttl = &expiry }) } func withAppLockOptionRetries(retries int) appLockOption { return appLockOptionFunc(func(o *appLockOptions) { o.maxRetries = &retries }) } var ( appLockOptionMaxRetries = math.MaxInt32 ) func withAppLockOptionInfiniteRetries() appLockOption { return appLockOptionFunc(func(o *appLockOptions) { o.maxRetries = &appLockOptionMaxRetries }) } func withAppLockOptionRetryDelay(retryDelay time.Duration) appLockOption { return appLockOptionFunc(func(o *appLockOptions) { o.retryDelay = &retryDelay }) }