locker

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 20, 2021 License: MIT Imports: 7 Imported by: 0

README

go-locker

Build Status Coverage Status Go Reference GoDoc Go Report Card

Distributed locking using Redis.

Example usage:

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/da440dil/go-locker"
	"github.com/go-redis/redis/v8"
)

func main() {
	client := redis.NewClient(&redis.Options{})
	defer client.Close()

	ctx := context.Background()
	key := "key"
	err := client.Del(ctx, key).Err()
	requireNoError(err)

	l := locker.NewLocker(client, 100*time.Millisecond)

	var wg sync.WaitGroup
	lockUnlock := func(id int) {
		wg.Add(1)
		go func() {
			defer wg.Done()

			r, err := l.Lock(ctx, key)
			requireNoError(err)
			if !r.OK() {
				fmt.Printf("Failed to apply lock #%d, retry after %v\n", id, r.TTL())
				return
			}
			fmt.Printf("Lock #%d applied\n", id)
			time.Sleep(50 * time.Millisecond)
			res, err := r.Lock.Lock(ctx)
			requireNoError(err)
			if !res.OK() {
				fmt.Printf("Failed to extend lock #%d, retry after %v\n", id, res.TTL())
				return
			}
			fmt.Printf("Lock #%d extended\n", id)
			time.Sleep(50 * time.Millisecond)
			ok, err := r.Unlock(ctx)
			requireNoError(err)
			if !ok {
				fmt.Printf("Failed to release lock #%d\n", id)
				return
			}
			fmt.Printf("Lock #%d released\n", id)
		}()
	}
	lockUnlock(1)
	lockUnlock(2)
	wg.Wait()
	// Output (may differ on each run because of concurrent execution):
	// Lock #1 applied
	// Failed to apply lock #2, retry after 99ms
	// Lock #1 extended
	// Lock #1 released
}

func requireNoError(err error) {
	if err != nil {
		panic(err)
	}
}

Documentation

Overview

Package locker provides functions for distributed locking.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnexpectedRedisResponse = errors.New("locker: unexpected redis response")

ErrUnexpectedRedisResponse is the error returned when Redis command returns response of unexpected type.

Functions

This section is empty.

Types

type Lock

type Lock struct {
	// contains filtered or unexported fields
}

Lock implements distributed locking.

func (Lock) Lock

func (lock Lock) Lock(ctx context.Context) (Result, error)

Lock applies the lock.

func (Lock) Unlock

func (lock Lock) Unlock(ctx context.Context) (bool, error)

Unlock releases the lock.

type LockResult added in v0.3.0

type LockResult struct {
	Lock
	Result
}

LockResult contains new lock and result of applying the lock.

type Locker

type Locker struct {
	// contains filtered or unexported fields
}

Locker defines parameters for creating new lock.

func NewLocker

func NewLocker(client RedisClient, ttl time.Duration, options ...Option) *Locker

NewLocker creates new locker.

func (*Locker) Lock

func (locker *Locker) Lock(ctx context.Context, key string) (LockResult, error)

Lock creates and applies new lock.

type Option added in v0.0.11

type Option func(locker *Locker)

Option is function for setting locker options.

func WithRandReader added in v0.0.12

func WithRandReader(r io.Reader) Option

WithRandReader sets random generator to generate a lock token. By default equals crypto/rand.Reader.

func WithRandSize added in v0.0.12

func WithRandSize(n int) Option

WithRandSize sets bytes size to read from random generator to generate a lock token. Must be greater than 0. By default equals 16.

type RedisClient added in v0.2.0

type RedisClient interface {
	Eval(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd
	EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *redis.Cmd
	ScriptExists(ctx context.Context, hashes ...string) *redis.BoolSliceCmd
	ScriptLoad(ctx context.Context, script string) *redis.StringCmd
}

RedisClient is redis scripter interface.

type Result added in v0.2.0

type Result int64

Result of applying a lock.

func (Result) OK added in v0.2.0

func (r Result) OK() bool

OK is operation success flag.

func (Result) TTL added in v0.2.0

func (r Result) TTL() time.Duration

TTL of a lock. Makes sense if operation failed, otherwise ttl is less than 0.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL