etcd3locker: Update formatting of docs; timeout -> ttl substitution (#216)
* Update formatting of docs; timeout -> ttl substitution * Add link to etcd3 locker in main README.md
This commit is contained in:
parent
3549a75e8c
commit
a4a6ef5a1c
|
@ -219,6 +219,7 @@ useful tools:
|
||||||
* [**gcsstore**](https://godoc.org/github.com/tus/tusd/gcsstore): A storage backend using Google cloud storage
|
* [**gcsstore**](https://godoc.org/github.com/tus/tusd/gcsstore): A storage backend using Google cloud storage
|
||||||
* [**memorylocker**](https://godoc.org/github.com/tus/tusd/memorylocker): An in-memory locker for handling concurrent uploads
|
* [**memorylocker**](https://godoc.org/github.com/tus/tusd/memorylocker): An in-memory locker for handling concurrent uploads
|
||||||
* [**consullocker**](https://godoc.org/github.com/tus/tusd/consullocker): A locker using the distributed Consul service
|
* [**consullocker**](https://godoc.org/github.com/tus/tusd/consullocker): A locker using the distributed Consul service
|
||||||
|
* [**etcd3locker**](https://godoc.org/github.com/tus/tusd/etcd3locker): A locker using the distributed KV etcd3 store
|
||||||
* [**limitedstore**](https://godoc.org/github.com/tus/tusd/limitedstore): A storage wrapper limiting the total used space for uploads
|
* [**limitedstore**](https://godoc.org/github.com/tus/tusd/limitedstore): A storage wrapper limiting the total used space for uploads
|
||||||
|
|
||||||
## Running the testsuite
|
## Running the testsuite
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// Tested on etcd 3.1+
|
// Package etcd3locker provides a locking mechanism using an etcd3 cluster.
|
||||||
|
// Tested on etcd 3.1/3.2./3.3
|
||||||
package etcd3locker
|
package etcd3locker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -22,6 +23,7 @@ func newEtcd3Lock(session *concurrency.Session, id string) *etcd3Lock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acquires a lock from etcd3
|
||||||
func (lock *etcd3Lock) Acquire() error {
|
func (lock *etcd3Lock) Acquire() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -38,10 +40,12 @@ func (lock *etcd3Lock) Acquire() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Releases a lock from etcd3
|
||||||
func (lock *etcd3Lock) Release() error {
|
func (lock *etcd3Lock) Release() error {
|
||||||
return lock.Mutex.Unlock(context.Background())
|
return lock.Mutex.Unlock(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Closes etcd3 session
|
||||||
func (lock *etcd3Lock) CloseSession() error {
|
func (lock *etcd3Lock) CloseSession() error {
|
||||||
return lock.Session.Close()
|
return lock.Session.Close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,41 +2,41 @@
|
||||||
//
|
//
|
||||||
// To initialize a locker, a pre-existing connected etcd3 client must be present
|
// To initialize a locker, a pre-existing connected etcd3 client must be present
|
||||||
//
|
//
|
||||||
// client, err := clientv3.New(clientv3.Config{
|
// client, err := clientv3.New(clientv3.Config{
|
||||||
// Endpoints: []string{harness.Endpoint},
|
// Endpoints: []string{harness.Endpoint},
|
||||||
// DialTimeout: 5 * time.Second,
|
// DialTimeout: 5 * time.Second,
|
||||||
// })
|
// })
|
||||||
//
|
//
|
||||||
// For the most basic locker (e.g. non-shared etcd3 cluster / use default TTLs),
|
// For the most basic locker (e.g. non-shared etcd3 cluster / use default TTLs),
|
||||||
// a locker can be instantiated like the following:
|
// a locker can be instantiated like the following:
|
||||||
//
|
//
|
||||||
// locker, err := etcd3locker.New(client)
|
// locker, err := etcd3locker.New(client)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return nil, fmt.Errorf("Failed to create etcd locker: %v", err.Error())
|
// return nil, fmt.Errorf("Failed to create etcd locker: %v", err.Error())
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// The locker will need to be included in composer that is used by tusd:
|
// The locker will need to be included in composer that is used by tusd:
|
||||||
//
|
//
|
||||||
// composer := tusd.NewStoreComposer()
|
// composer := tusd.NewStoreComposer()
|
||||||
// locker.UseIn(composer)
|
// locker.UseIn(composer)
|
||||||
//
|
//
|
||||||
// For a shared etcd3 cluster, you may want to modify the prefix that etcd3locker uses:
|
// For a shared etcd3 cluster, you may want to modify the prefix that etcd3locker uses:
|
||||||
//
|
//
|
||||||
// locker, err := etcd3locker.NewWithPrefix(client, "my-prefix")
|
// locker, err := etcd3locker.NewWithPrefix(client, "my-prefix")
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return nil, fmt.Errorf("Failed to create etcd locker: %v", err.Error())
|
// return nil, fmt.Errorf("Failed to create etcd locker: %v", err.Error())
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// For full control over all options, an etcd3.LockerOptions may be passed into
|
// For full control over all options, an etcd3.LockerOptions may be passed into
|
||||||
// etcd3.NewWithLockerOptions like the following example:
|
// etcd3.NewWithLockerOptions like the following example:
|
||||||
//
|
//
|
||||||
// ttl := 15 // seconds
|
// ttl := 15 // seconds
|
||||||
// options := etcd3locker.NewLockerOptions(ttl, "my-prefix")
|
// options := etcd3locker.NewLockerOptions(ttl, "my-prefix")
|
||||||
// locker, err := etcd3locker.NewWithLockerOptions(client, options)
|
// locker, err := etcd3locker.NewWithLockerOptions(client, options)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return nil, fmt.Errorf("Failed to create etcd locker: %v", err.Error())
|
// return nil, fmt.Errorf("Failed to create etcd locker: %v", err.Error())
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Tested on etcd 3.1/3.2/3.3
|
// Tested on etcd 3.1/3.2/3.3
|
||||||
//
|
//
|
||||||
|
@ -64,10 +64,10 @@ type Etcd3Locker struct {
|
||||||
// locks is used for storing Etcd3Locks before they are
|
// locks is used for storing Etcd3Locks before they are
|
||||||
// unlocked. If you want to release a lock, you need the same locker
|
// unlocked. If you want to release a lock, you need the same locker
|
||||||
// instance and therefore we need to save them temporarily.
|
// instance and therefore we need to save them temporarily.
|
||||||
locks map[string]*etcd3Lock
|
locks map[string]*etcd3Lock
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
prefix string
|
prefix string
|
||||||
sessionTimeout int
|
sessionTtl int
|
||||||
}
|
}
|
||||||
|
|
||||||
// New constructs a new locker using the provided client.
|
// New constructs a new locker using the provided client.
|
||||||
|
@ -85,7 +85,7 @@ func NewWithPrefix(client *etcd3.Client, prefix string) (*Etcd3Locker, error) {
|
||||||
// This method may be used if we want control over both prefix/session TTLs. This is used for testing in particular.
|
// This method may be used if we want control over both prefix/session TTLs. This is used for testing in particular.
|
||||||
func NewWithLockerOptions(client *etcd3.Client, opts LockerOptions) (*Etcd3Locker, error) {
|
func NewWithLockerOptions(client *etcd3.Client, opts LockerOptions) (*Etcd3Locker, error) {
|
||||||
locksMap := map[string]*etcd3Lock{}
|
locksMap := map[string]*etcd3Lock{}
|
||||||
return &Etcd3Locker{Client: client, prefix: opts.Prefix(), sessionTimeout: opts.Timeout(), locks: locksMap, mutex: sync.Mutex{}}, nil
|
return &Etcd3Locker{Client: client, prefix: opts.Prefix(), sessionTtl: opts.Ttl(), locks: locksMap, mutex: sync.Mutex{}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseIn adds this locker to the passed composer.
|
// UseIn adds this locker to the passed composer.
|
||||||
|
@ -137,7 +137,7 @@ func (locker *Etcd3Locker) UnlockUpload(id string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (locker *Etcd3Locker) createSession() (*concurrency.Session, error) {
|
func (locker *Etcd3Locker) createSession() (*concurrency.Session, error) {
|
||||||
return concurrency.NewSession(locker.Client, concurrency.WithTTL(locker.sessionTimeout))
|
return concurrency.NewSession(locker.Client, concurrency.WithTTL(locker.sessionTtl))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (locker *Etcd3Locker) getId(id string) string {
|
func (locker *Etcd3Locker) getId(id string) string {
|
||||||
|
|
|
@ -10,32 +10,38 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type LockerOptions struct {
|
type LockerOptions struct {
|
||||||
timeoutSeconds int
|
ttl int
|
||||||
prefix string
|
prefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultLockerOptions() instantiates an instance of LockerOptions
|
||||||
|
// with default 60 second time to live and an etcd3 prefix of "/tusd"
|
||||||
func DefaultLockerOptions() LockerOptions {
|
func DefaultLockerOptions() LockerOptions {
|
||||||
return LockerOptions{
|
return LockerOptions{
|
||||||
timeoutSeconds: 60,
|
ttl: 60,
|
||||||
prefix: "/tusd",
|
prefix: "/tusd",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLockerOptions(timeout int, prefix string) LockerOptions {
|
// NewLockerOptions instantiates an instance of LockerOptions with a
|
||||||
|
// provided TTL (time to live) and string prefix for keys to be stored in etcd3
|
||||||
|
func NewLockerOptions(ttl int, prefix string) LockerOptions {
|
||||||
return LockerOptions{
|
return LockerOptions{
|
||||||
timeoutSeconds: timeout,
|
ttl: ttl,
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LockerOptions) Timeout() int {
|
// Returns the TTL (time to live) of sessions in etcd3
|
||||||
if l.timeoutSeconds == 0 {
|
func (l *LockerOptions) Ttl() int {
|
||||||
|
if l.ttl == 0 {
|
||||||
return DefaultTtl
|
return DefaultTtl
|
||||||
} else {
|
} else {
|
||||||
return l.timeoutSeconds
|
return l.ttl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the string prefix used to store keys in etcd3
|
||||||
func (l *LockerOptions) Prefix() string {
|
func (l *LockerOptions) Prefix() string {
|
||||||
prefix := l.prefix
|
prefix := l.prefix
|
||||||
if !strings.HasPrefix(prefix, "/") {
|
if !strings.HasPrefix(prefix, "/") {
|
||||||
|
@ -49,10 +55,12 @@ func (l *LockerOptions) Prefix() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LockerOptions) SetTimeout(timeout int) {
|
// Set etcd3 session TTL (time to live)
|
||||||
l.timeoutSeconds = timeout
|
func (l *LockerOptions) SetTtl(ttl int) {
|
||||||
|
l.ttl = ttl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set string prefix to be used in keys stored into etcd3 by the locker
|
||||||
func (l *LockerOptions) SetPrefix(prefix string) {
|
func (l *LockerOptions) SetPrefix(prefix string) {
|
||||||
l.prefix = prefix
|
l.prefix = prefix
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue