dlock

package
v0.0.0-...-0e9fed5 Latest Latest
Warning

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

Go to latest
Published: Dec 29, 2023 License: MIT Imports: 9 Imported by: 1

README

Distributed lock

The idea about this package is to provide some means to lock an object. The object is your arbitrary chosen name. This implementation is inspired by redislock, but aims to be simpler by not requiring redis and is written completely in Golang.

The name implies that this is a distributed lock, and that is handles by providing a REST API (and the golang client, so you can use it in a distributed manner). There is also a gRPC implementation if you prefer to use that instead.

Three methods are exposed:

  • Lock - returns true if the lock was acquired
  • Unlock - returns true if the lock was released
  • IsPresent - returns true if the lock exists

They all take one argument - the name of the lock and returns true if successful/present.

To run only locally

lock := dlock.NewDLockServer()
if !lock.Lock("myObject") {
	panic("lock not obtained")
}

To run as a server

lock := dlock.NewDLockServer(dlock.WithPrefix("/lock/"))
http.Handle("/lock/", lock)
http.ListenAndServe(":8080", nil)

Now you can connect your client. When using WithPrefix as shown above you can use the lock both locally and remote at the same time. (By default the lock that is acquired is the full request URL.)

To run as a client

lock := dlock.DLockClient{basePath: "http://localhost:8080/lock"}
if !lock.Lock("myObject") {
    panic("lock not obtained")
}

If the server is not available, then all calls will return false.

There are options you can add to include extra headers, use your own context etc.

Authentication

If you want to add authentication you will need to add this as headers on the client. On the server that is handled using some kind of middleware.

Documentation

Index

Constants

View Source
const (
	LoggerName  = "name"  // name variable for logging
	LoggerLock  = "lock"  // name for lock status
	LoggerValue = "value" // value for a number

)

Variables

This section is empty.

Functions

This section is empty.

Types

type ClientOption

type ClientOption func(server *DLockClient)

ClientOption is used for passing options into DLockServer

func WithClient

func WithClient(c *http.Client) ClientOption

WithClient configures the HTTP Client to use

func WithClientContext

func WithClientContext(ctx context.Context) ClientOption

WithClientContext defines a context to be used for all requests. As an alternative you can define your own http.Client and configure timeout there.

func WithClientHeaders

func WithClientHeaders(h map[string]string) ClientOption

WithClientHeaders configures a map of headers to add to all requests

func WithClientLogger

func WithClientLogger(logger *slog.Logger) ClientOption

WithClientLogger configures a logger

type DLockClient

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

DLockClient represents a client that connects to a server

func NewDlockClient

func NewDlockClient(base string, opts ...ClientOption) *DLockClient

NewDlockClient returns a new client

func (*DLockClient) IsPresent

func (d *DLockClient) IsPresent(name string) bool

IsPresent checks if the lock is present

func (*DLockClient) Lock

func (d *DLockClient) Lock(name string) bool

Lock tries to acquire a read/write lock

func (*DLockClient) RLock

func (d *DLockClient) RLock(name string) bool

RLock tries to acquire a read-only lock

func (*DLockClient) RUnlock

func (d *DLockClient) RUnlock(name string) bool

RUnlock releases a r/o lock

func (*DLockClient) Unlock

func (d *DLockClient) Unlock(name string) bool

Unlock releases a r/w lock

type DLockServer

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

DLockServer is a distributed lock

func NewDLockServer

func NewDLockServer(opts ...ServerOption) *DLockServer

NewDLockServer returns a new instance of a lock

func (*DLockServer) Count

func (d *DLockServer) Count() int

Count returns the number of objects that are locked

func (*DLockServer) IsPresent

func (d *DLockServer) IsPresent(name string) bool

IsPresent checks if a lock is present and returns the result

func (*DLockServer) Lock

func (d *DLockServer) Lock(name string) (result bool)

Lock creates a lock, returns true if lock was created. On false the lock already exist.

func (*DLockServer) RLock

func (d *DLockServer) RLock(name string) (result bool)

RLock returns true if a read lock could be obtained. Multiple read locks can be given.

func (*DLockServer) RUnlock

func (d *DLockServer) RUnlock(name string) (result bool)

RUnlock unlocks a read lock

func (*DLockServer) ServeHTTP

func (d *DLockServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP is our HTTP handler. Any logging and authentication here should be done using a middleware.

func (*DLockServer) Unlock

func (d *DLockServer) Unlock(name string) (result bool)

Unlock unlocks the lock, returning true if the lock was unlocked, false if it does not exist. An Unlock will also delete any read locks.

type DLocker

type DLocker interface {
	Lock(string) bool      // lock an object, returns true if you got the lock
	Unlock(string) bool    // unlock and object, returns true if you unlocked it
	RLock(string) bool     // lock read-only (multiple locks supported)
	RUnlock(string) bool   // unlock a read-only lock
	IsPresent(string) bool // returns true if the object is present and locked
}

DLocker is an interface that can represent both the server and the client after startup

type DNoLocker

type DNoLocker struct {
}

DNoLocker is a locker that never locks and always succeeds. This is meant for scenarios where you don't need a real lock, and just need a placeholder.

func (*DNoLocker) IsPresent

func (d *DNoLocker) IsPresent(_ string) bool

func (*DNoLocker) Lock

func (d *DNoLocker) Lock(_ string) bool

func (*DNoLocker) RLock

func (d *DNoLocker) RLock(_ string) bool

func (*DNoLocker) RUnlock

func (d *DNoLocker) RUnlock(_ string) bool

func (*DNoLocker) Unlock

func (d *DNoLocker) Unlock(_ string) bool

type ServerOption

type ServerOption func(server *DLockServer)

ServerOption is used for passing options into DLockServer

func CleanupInterval

func CleanupInterval(interval time.Duration) ServerOption

CleanupInterval defines how often to clean up stale locks

func WithLogger

func WithLogger(logger *slog.Logger) ServerOption

WithLogger specifies what logger to use

func WithPrefix

func WithPrefix(prefix string) ServerOption

WithPrefix specifies a prefix that is removed from all HTTP calls before stored into memory. When used, you can do both local and remote calls at the same time on the same object name.

Jump to

Keyboard shortcuts

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