2018-04-13 04:02:30 +00:00
|
|
|
package impl
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
cc "clientlibrary/common"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
// We will consider leases to be expired if they are more than 90 days.
|
|
|
|
|
MAX_ABS_AGE_NANOS = int64(90 * 24 * time.Hour)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Lease structure contains data pertaining to a Lease. Distributed systems may use leases to partition work across a
|
|
|
|
|
// fleet of workers. Each unit of work (identified by a leaseKey) has a corresponding Lease. Every worker will contend
|
|
|
|
|
// for all leases - only one worker will successfully take each one. The worker should hold the lease until it is ready to stop
|
|
|
|
|
// processing the corresponding unit of work, or until it fails. When the worker stops holding the lease, another worker will
|
|
|
|
|
// take and hold the lease.
|
|
|
|
|
type Lease struct {
|
2018-04-17 16:25:41 +00:00
|
|
|
// shard-id
|
|
|
|
|
leaseKey string
|
|
|
|
|
// worker#
|
|
|
|
|
leaseOwner string
|
|
|
|
|
// ccounter incremented periodically
|
2018-04-13 04:02:30 +00:00
|
|
|
leaseCounter int64
|
|
|
|
|
|
|
|
|
|
// This field is used to prevent updates to leases that we have lost and re-acquired. It is deliberately not
|
|
|
|
|
// persisted in DynamoDB and excluded from hashCode and equals.
|
|
|
|
|
concurrencyToken string
|
|
|
|
|
|
|
|
|
|
// This field is used by LeaseRenewer and LeaseTaker to track the last time a lease counter was incremented. It is
|
|
|
|
|
// deliberately not persisted in DynamoDB and excluded from hashCode and equals.
|
|
|
|
|
lastCounterIncrementNanos int64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CloneLease to clone a lease object
|
|
|
|
|
func CopyLease(lease *Lease) *Lease {
|
|
|
|
|
return &Lease{
|
|
|
|
|
leaseKey: lease.leaseKey,
|
|
|
|
|
leaseOwner: lease.leaseOwner,
|
|
|
|
|
leaseCounter: lease.leaseCounter,
|
|
|
|
|
concurrencyToken: lease.concurrencyToken,
|
|
|
|
|
lastCounterIncrementNanos: lease.lastCounterIncrementNanos,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetLeaseKey retrieves leaseKey - identifies the unit of work associated with this lease.
|
|
|
|
|
func (l *Lease) GetLeaseKey() string {
|
|
|
|
|
return l.leaseKey
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetLeaseOwner gets current owner of the lease, may be "".
|
|
|
|
|
func (l *Lease) GetLeaseOwner() string {
|
|
|
|
|
return l.leaseOwner
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetLeaseCounter retrieves leaseCounter which is incremented periodically by the holder of the lease. Used for optimistic locking.
|
|
|
|
|
func (l *Lease) GetLeaseCounter() int64 {
|
|
|
|
|
return l.leaseCounter
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetConcurrencyToken returns concurrency token
|
|
|
|
|
func (l *Lease) GetConcurrencyToken() string {
|
|
|
|
|
return l.concurrencyToken
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetLastCounterIncrementNanos returns concurrency token
|
|
|
|
|
func (l *Lease) GetLastCounterIncrementNanos() int64 {
|
|
|
|
|
return l.lastCounterIncrementNanos
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetLeaseKey sets leaseKey - LeaseKey is immutable once set.
|
|
|
|
|
func (l *Lease) SetLeaseKey(leaseKey string) error {
|
|
|
|
|
if len(l.leaseKey) > 0 {
|
|
|
|
|
return cc.IllegalArgumentError.MakeErr().WithDetail("LeaseKey is immutable once set")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
l.leaseKey = leaseKey
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetLeaseOwner set current owner of the lease, may be "".
|
|
|
|
|
func (l *Lease) SetLeaseOwner(leaseOwner string) {
|
|
|
|
|
l.leaseOwner = leaseOwner
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetLeaseCounter sets leaseCounter which is incremented periodically by the holder of the lease. Used for optimistic locking.
|
|
|
|
|
func (l *Lease) SetLeaseCounter(leaseCounter int64) {
|
|
|
|
|
l.leaseCounter = leaseCounter
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetConcurrencyToken
|
|
|
|
|
func (l *Lease) SetConcurrencyToken(concurrencyToken string) {
|
|
|
|
|
l.concurrencyToken = concurrencyToken
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetLastCounterIncrementNanos returns concurrency token
|
|
|
|
|
func (l *Lease) SetLastCounterIncrementNanos(lastCounterIncrementNanos int64) {
|
|
|
|
|
l.lastCounterIncrementNanos = lastCounterIncrementNanos
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsExpired to check whether lease expired using
|
|
|
|
|
// @param leaseDurationNanos duration of lease in nanoseconds
|
|
|
|
|
// @param asOfNanos time in nanoseconds to check expiration as-of
|
|
|
|
|
// @return true if lease is expired as-of given time, false otherwise
|
|
|
|
|
func (l *Lease) IsExpired(leaseDurationNanos, asOfNanos int64) bool {
|
|
|
|
|
if l.lastCounterIncrementNanos == 0 {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
age := asOfNanos - l.lastCounterIncrementNanos
|
|
|
|
|
if age > MAX_ABS_AGE_NANOS {
|
|
|
|
|
return true
|
|
|
|
|
} else {
|
|
|
|
|
return age > leaseDurationNanos
|
|
|
|
|
}
|
|
|
|
|
}
|