locker

package
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Feb 9, 2022 License: MIT Imports: 16 Imported by: 3

Documentation

Index

Constants

View Source
const (
	// UnknownLockProviderKind is the default kind and is unimplmeneted
	UnknownLockProviderKind = iota

	// PostgresLockProviderKind represents an implementation of the LockProvider interface that uses Postgres as the underlying store
	PostgresLockProviderKind

	// FakeLockProviderKind represents an implementation of the LockProvider interfaces that uses an in-memory store, suitable for tests
	FakeLockProviderKind
)

Variables

View Source
var ErrLockPreempted = errors.New("lock was preemptepd while waiting for the lock")

Functions

This section is empty.

Types

type FakeLockProvider added in v0.8.0

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

FakeLockProvider can serve as a lock provider with no external dependencies

func (*FakeLockProvider) LockKey added in v0.8.0

func (flp *FakeLockProvider) LockKey(ctx context.Context, repo string, pr uint) (int64, error)

func (*FakeLockProvider) New added in v0.8.0

func (flp *FakeLockProvider) New(ctx context.Context, key int64, event string) (PreemptableLock, error)

type FakePreemptableLock

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

func (*FakePreemptableLock) Lock

func (fpl *FakePreemptableLock) Lock(ctx context.Context) (<-chan NotificationPayload, error)

func (*FakePreemptableLock) Notify added in v0.8.0

func (fpl *FakePreemptableLock) Notify(ctx context.Context) error

func (*FakePreemptableLock) Unlock

func (fpl *FakePreemptableLock) Unlock(ctx context.Context) error

type LockProvider

type LockProvider interface {
	New(ctx context.Context, key int64, event string) (PreemptableLock, error)
	LockKey(ctx context.Context, repo string, pr uint) (int64, error)
}

LockProvider describes an object capable of creating distributed locks. You may provide your own int64 key or obtain one for a given Repo/PR.

func NewLockProvider added in v0.8.0

func NewLockProvider(kind LockProviderKind, options ...LockProviderOption) (LockProvider, error)

NewLockProvider returns an implementation of the LockProvider interface. It accepts an arbitrary number of LockProviderOptions and sets some opinonated default values if the option is not explicitly set.

type LockProviderConfig added in v0.8.0

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

LockProviderConfig sets configuration values that can be shared between LockProvider implementations.

type LockProviderKind added in v0.8.0

type LockProviderKind int

LockProviderKind enumerates the different LockProvider implementations

type LockProviderOption added in v0.8.0

type LockProviderOption func(*LockProviderConfig)

LockProviderOptions allows clients to configure different aspects for the LockProvider return from NewLockProvider

func WithLockTimeout added in v0.8.0

func WithLockTimeout(lockWait time.Duration) LockProviderOption

WithLockTimeout sets the duration for which the lock will block while attempting to lock, before it gives up and returns an error.

func WithMaxLockDuration added in v0.8.0

func WithMaxLockDuration(duration time.Duration) LockProviderOption

WithMaxLockDuration sets the duration for which the lock will wait before automatically unlocking the lock. This can be used to protect against the holder of the lock getting blocked or not being able to unlock the lock.

func WithPostgresBackend added in v0.8.0

func WithPostgresBackend(postgresURI string, apmServiceName string) LockProviderOption

WithPostgresBackend allows for a distributed lock provider backed by Postgres. APM traces can also be enabled with the configured service name.

func WithPreemptionTimeout added in v0.8.0

func WithPreemptionTimeout(duration time.Duration) LockProviderOption

WithPreemptionTimeout sets the duration for which the lock will wait for the holder to respect a notification and release the lock. If a notification is sent to the lock, the lock will be released after this duration no matter what the holder does. This provides a mechanism for releasing the lock quickly in scenarios where the holder of the lock may be blocked indefinitely.

type NotificationPayload added in v0.8.0

type NotificationPayload struct {
	// ID is required so that we can ensure the message came from another party.
	ID uuid.UUID `json:"id"`

	// Message provides some context as to why the notification was generated.
	// Useful for logging purposes.
	Message string `json:"event"`

	// The key that this Notification Payload pertains to
	LockKey int64 `json:lockKey`
}

NotificationPayload represents the content of messages sent to the lock holder.

type PostgresEnvLock added in v0.8.0

type PostgresEnvLock struct {
	LockKey     int64
	Repo        string
	PullRequest uint
}

PostgresEnvLock models a distributed lock associated with a unique repo/PR combination

func (PostgresEnvLock) Columns added in v0.8.0

func (el PostgresEnvLock) Columns() string

func (PostgresEnvLock) ScanValues added in v0.8.0

func (el PostgresEnvLock) ScanValues() []interface{}

type PostgresLock added in v0.8.0

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

func NewPostgresLock added in v0.8.0

func NewPostgresLock(ctx context.Context, db *sqlx.DB, key int64, connInfo, message string, conf LockProviderConfig) (pl *PostgresLock, err error)

func (*PostgresLock) Lock added in v0.8.0

func (pl *PostgresLock) Lock(ctx context.Context) (<-chan NotificationPayload, error)

func (*PostgresLock) Notify added in v0.8.0

func (pl *PostgresLock) Notify(ctx context.Context) error

Notify lets other processes know that they should release the lock. In this case, we use the Postgres NOTIFY command to let the other processes know. It is up to the other locks to LISTEN and release the lock accordingly.

func (*PostgresLock) Unlock added in v0.8.0

func (pl *PostgresLock) Unlock(ctx context.Context) error

Unlock is an idempotent method that unlocks the lock if it is still held.

type PostgresLockProvider added in v0.8.0

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

func (*PostgresLockProvider) LockKey added in v0.8.0

func (plp *PostgresLockProvider) LockKey(ctx context.Context, repo string, pullRequest uint) (int64, error)

func (*PostgresLockProvider) New added in v0.8.0

func (plp *PostgresLockProvider) New(ctx context.Context, key int64, event string) (PreemptableLock, error)

type PreemptableLock

type PreemptableLock interface {
	// Lock locks the preemptable lock. If it fails to lock, or is preempted before locking, it should return an error
	Lock(ctx context.Context) (<-chan NotificationPayload, error)

	// Unlock unlocks the preemptable lock. It should clean up any underlying resources
	Unlock(ctx context.Context) error

	// Notify informs the current lock holder that they should unlock the lock
	Notify(ctx context.Context) error
}

PreemptableLock describes an object that acts as a Lock that can signal to peers that they should unlock Preemptable locks are single use. Once you unlock the lock, underlying resources will be cleaned up

type PreemptiveLocker

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

PreemptiveLocker represents a distributed lock where callers can be preempted while waiting for the lock to be released or while holding the lock. High level, the algorithm is as follows: - Client A calls Lock() which returns immediately, Client A now has the lock. Client A periodically ensures the session is still alive. If Client A dies, the session expires and the lock is automatically released. - Client B calls Lock() which blocks since the lock is held by Client A. - Client A receives a value on the channel returned from the Lock() call indicating Client A should release the lock ASAP - Client C calls Lock() which blocks - Client B's invocation of Lock() returns with an error indicating it was preempted while waiting for the lock to release - Client A calls Unlock() - Client C's invocation of Lock() returns successfully

func (*PreemptiveLocker) Lock

func (p *PreemptiveLocker) Lock(ctx context.Context) (ch <-chan NotificationPayload, err error)

Lock locks the lock and returns a channel used to signal if the lock should be released ASAP. If the lock is currently in use, this method will block until the lock is released. If the caller is preempted while waiting for the lock to be released, an error is returned.

func (*PreemptiveLocker) Release

func (p *PreemptiveLocker) Release(ctx context.Context) (err error)

Release releases the lock. It is recommended to pass in a different context than the one provided for Lock, since that context could be canceled.

type PreemptiveLockerConfig added in v0.8.0

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

PreemptiveLockerConfig contains values for adjusting how the PreemptiveLocker behaves

type PreemptiveLockerFactory added in v0.8.0

type PreemptiveLockerFactory func(repo string, pr uint, event string) *PreemptiveLocker

func NewFakePreemptiveLockerFactory added in v0.8.0

func NewFakePreemptiveLockerFactory(providerOpts []LockProviderOption, lockerOpts ...PreemptiveLockerOption) (PreemptiveLockerFactory, error)

NewFakePreemptiveLockerFactory will create a PreemptiveLockerFactory that makes use of a FakeLockProvider. This is suitable for tests, where postgres might not be available or wanted.

func NewPostgresPreemptiveLockerFactory added in v0.8.0

func NewPostgresPreemptiveLockerFactory(postgresURI, apmServiceName string, providerOpts []LockProviderOption, lockerOpts ...PreemptiveLockerOption) (PreemptiveLockerFactory, error)

NewPostgresPreemptiveLockerFactory will create a PreemptiveLockerFactory that makes use of a PostgresLockProvider.

func NewPreemptiveLockerFactory added in v0.8.0

func NewPreemptiveLockerFactory(provider LockProvider, opts ...PreemptiveLockerOption) (PreemptiveLockerFactory, error)

NewPreemptiveLockerFactory

type PreemptiveLockerOption added in v0.8.0

type PreemptiveLockerOption func(*PreemptiveLockerConfig)

func WithAPMServiceName added in v0.8.0

func WithAPMServiceName(name string) PreemptiveLockerOption

func WithLockDelay added in v0.8.0

func WithLockDelay(lockDelay time.Duration) PreemptiveLockerOption

Jump to

Keyboard shortcuts

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