lease

package
v0.0.0-...-8ff1004 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2019 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

The lease package exists to implement distributed lease management on top of mgo/txn, and to expose assert operations that allow us to gate other mgo/txn transactions on lease state. This necessity has affected the package; but, apart from leaking assertion operations, it functions as a distributed lease- management system with various useful properties.

These properties of course rest upon assumptions; ensuring the validity of the following statements is the job of the client.

  • The lease package has exclusive access to any collection it's configured to use. (Please don't store anything else in there.)

  • Given any (collection,namespace) pair, any client Id will be unique at any given point in time. (Run no more than one per namespace per server, and identify them according to where they're running).

  • Global time (i.e. the time returned by the provided global clock) passes no faster than wall-clock time.

So long as the above holds true, the following statements will too:

  • A successful ClaimLease guarantees lease ownership until *at least* the requested duration after the start of the call. (It does *not* guaranntee any sort of timely expiry.)

  • A successful ExtendLease makes the same guarantees. (In particular, note that this cannot cause a lease to be shortened; but that success may indicate ownership is guaranteed for longer than requested.)

  • ExpireLease will only succeed when the global time is after the (start+duration) written to the lease.

Schema design -------------

For each namespace, we store a single document per lease. The lease document holds the name, holder, global start time, duration, and writer of the lease.

Client usage considerations ---------------------------

  • Client operates at a relatively low level of abstraction. Claiming a held lease will fail, even on behalf of the holder; expiring an expired lease will fail; but at least we can allow lease extensions to race benignly, because they don't involve ownership change and thus can't break promises.

  • ErrInvalid is normal and expected; you should never pass that on to your own clients, because it indicates that you tried to manipulate the client in an impossible way. You can and should inspect Leases() and figure out what to do instead; that may well be "return an error", but please be sure to return your own error, suitable for your own level of abstraction.

  • You *probably* shouldn't ever need to actually call Refresh. It's perfectly safe to let state drift arbitrarily far out of sync; when you try to run operations, you will either succeed by luck despite your aged cache... or, if you fail, you'll get ErrInvalid and a fresh cache to inspect to find out recent state.

  • The expiry time returned via lease.Info is relative to the local system clock, not the global time. The expiry time should only be used for comparison with other local system clock times, and only with Go 1.9+ (i.e. because Go 1.9 introduced monotonic time components.)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClaimLeaseOps

func ClaimLeaseOps(
	namespace, name, holder, writer, collection string,
	globalTime time.Time, duration time.Duration,
) ([]txn.Op, error)

ClaimLeaseOps returns txn.Ops to write a new lease. The txn.Ops will fail if the lease document exists, regardless of whether it has expired.

func LookupLease

func LookupLease(coll mongo.Collection, namespace, name string) (leaseDoc, error)

LookupLease returns a lease claim if it exists. If it doesn't exist, expect to get an mgo.NotFoundError, otherwise expect to get

func NewStore

func NewStore(config StoreConfig) (lease.Store, error)

NewStore returns a new Store using the supplied config, or an error. Any of the following situations will prevent store creation:

  • invalid config
  • invalid lease data stored in the namespace

...but a returned Store will hold a recent cache of lease data and be ready to use. Stores do not need to be cleaned up themselves, but they will not function past the lifetime of their configured Mongo.

Types

type GlobalClock

type GlobalClock interface {

	// Now returns the current global clock time.
	//
	// Now is required to return monotonically increasing times.
	Now() (time.Time, error)
}

GlobalClock provides the global clock interface required by the lease package.

type LocalClock

type LocalClock interface {

	// Now returns the current, writer-local wall-clock time.
	//
	// Now is required to return times with a monotonic component,
	// as returned by Go 1.9 and onwards, such that local times
	// can be safely compared in the face of wall clock jumps.
	Now() time.Time
}

LocalClock provides the writer-local wall clock interface required by the lease package.

type Mongo

type Mongo interface {

	// RunTransaction should probably delegate to a jujutxn.Runner's Run method.
	RunTransaction(jujutxn.TransactionSource) error

	// GetCollection should probably call the mongo.CollectionFromName func.
	GetCollection(name string) (collection mongo.Collection, closer func())
}

Mongo exposes MongoDB operations for use by the lease package.

type StoreConfig

type StoreConfig struct {

	// Id uniquely identifies the store. Multiple stores with the same id
	// running concurrently will cause undefined behaviour.
	Id string

	// ModelUUID identifies the model the leases will be stored in.
	ModelUUID string

	// Namespace identifies a group of stores which operate on the same data.
	Namespace string

	// Collection names the MongoDB collection in which lease data is stored.
	Collection string

	// Mongo exposes the mgo[/txn] capabilities required by a Store.
	Mongo Mongo

	// LocalClock exposes the writer-local wall-clock time to a Store.
	LocalClock LocalClock

	// GlobalClock exposes the global clock to a Store.
	GlobalClock GlobalClock
}

StoreConfig contains the resources and information required to create a Store. Multiple stores can collaborate if they share a collection and namespace, so long as they do not share ids; but within a collection, stores for different namespaces will not interfere with one another, regardless of id.

Jump to

Keyboard shortcuts

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