mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
client: elevate context to caller of KeysAPI
This commit is contained in:
parent
f0760d6246
commit
17c6f21d68
@ -41,31 +41,30 @@ var (
|
|||||||
ErrKeyExists = errors.New("client: key already exists")
|
ErrKeyExists = errors.New("client: key already exists")
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewKeysAPI(c httpActionDo, to time.Duration) KeysAPI {
|
func NewKeysAPI(c httpActionDo) KeysAPI {
|
||||||
return &httpKeysAPI{
|
return &httpKeysAPI{
|
||||||
client: c,
|
client: c,
|
||||||
prefix: DefaultV2KeysPrefix,
|
prefix: DefaultV2KeysPrefix,
|
||||||
timeout: to,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDiscoveryKeysAPI(c httpActionDo, to time.Duration) KeysAPI {
|
func NewDiscoveryKeysAPI(c httpActionDo) KeysAPI {
|
||||||
return &httpKeysAPI{
|
return &httpKeysAPI{
|
||||||
client: c,
|
client: c,
|
||||||
prefix: "",
|
prefix: "",
|
||||||
timeout: to,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeysAPI interface {
|
type KeysAPI interface {
|
||||||
Create(key, value string, ttl time.Duration) (*Response, error)
|
Create(ctx context.Context, key, value string, ttl time.Duration) (*Response, error)
|
||||||
Get(key string) (*Response, error)
|
Get(ctx context.Context, key string) (*Response, error)
|
||||||
|
|
||||||
Watch(key string, idx uint64) Watcher
|
Watch(key string, idx uint64) Watcher
|
||||||
RecursiveWatch(key string, idx uint64) Watcher
|
RecursiveWatch(key string, idx uint64) Watcher
|
||||||
}
|
}
|
||||||
|
|
||||||
type Watcher interface {
|
type Watcher interface {
|
||||||
Next() (*Response, error)
|
Next(context.Context) (*Response, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Response struct {
|
type Response struct {
|
||||||
@ -90,10 +89,9 @@ func (n *Node) String() string {
|
|||||||
type httpKeysAPI struct {
|
type httpKeysAPI struct {
|
||||||
client httpActionDo
|
client httpActionDo
|
||||||
prefix string
|
prefix string
|
||||||
timeout time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *httpKeysAPI) Create(key, val string, ttl time.Duration) (*Response, error) {
|
func (k *httpKeysAPI) Create(ctx context.Context, key, val string, ttl time.Duration) (*Response, error) {
|
||||||
create := &createAction{
|
create := &createAction{
|
||||||
Prefix: k.prefix,
|
Prefix: k.prefix,
|
||||||
Key: key,
|
Key: key,
|
||||||
@ -104,9 +102,7 @@ func (k *httpKeysAPI) Create(key, val string, ttl time.Duration) (*Response, err
|
|||||||
create.TTL = &uttl
|
create.TTL = &uttl
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), k.timeout)
|
|
||||||
resp, body, err := k.client.Do(ctx, create)
|
resp, body, err := k.client.Do(ctx, create)
|
||||||
cancel()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -114,16 +110,14 @@ func (k *httpKeysAPI) Create(key, val string, ttl time.Duration) (*Response, err
|
|||||||
return unmarshalHTTPResponse(resp.StatusCode, body)
|
return unmarshalHTTPResponse(resp.StatusCode, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *httpKeysAPI) Get(key string) (*Response, error) {
|
func (k *httpKeysAPI) Get(ctx context.Context, key string) (*Response, error) {
|
||||||
get := &getAction{
|
get := &getAction{
|
||||||
Prefix: k.prefix,
|
Prefix: k.prefix,
|
||||||
Key: key,
|
Key: key,
|
||||||
Recursive: false,
|
Recursive: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), k.timeout)
|
|
||||||
resp, body, err := k.client.Do(ctx, get)
|
resp, body, err := k.client.Do(ctx, get)
|
||||||
cancel()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -160,9 +154,8 @@ type httpWatcher struct {
|
|||||||
nextWait waitAction
|
nextWait waitAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hw *httpWatcher) Next() (*Response, error) {
|
func (hw *httpWatcher) Next(ctx context.Context) (*Response, error) {
|
||||||
//TODO(bcwaldon): This needs to be cancellable by the calling user
|
httpresp, body, err := hw.client.Do(ctx, &hw.nextWait)
|
||||||
httpresp, body, err := hw.client.Do(context.Background(), &hw.nextWait)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/coreos/etcd/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
||||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/jonboulle/clockwork"
|
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/jonboulle/clockwork"
|
||||||
"github.com/coreos/etcd/client"
|
"github.com/coreos/etcd/client"
|
||||||
"github.com/coreos/etcd/pkg/types"
|
"github.com/coreos/etcd/pkg/types"
|
||||||
@ -110,7 +111,7 @@ func New(durl string, id types.ID, config string) (Discoverer, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dc := client.NewDiscoveryKeysAPI(c, client.DefaultRequestTimeout)
|
dc := client.NewDiscoveryKeysAPI(c)
|
||||||
return &discovery{
|
return &discovery{
|
||||||
cluster: token,
|
cluster: token,
|
||||||
id: id,
|
id: id,
|
||||||
@ -150,21 +151,25 @@ func (d *discovery) Discover() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *discovery) createSelf() error {
|
func (d *discovery) createSelf() error {
|
||||||
resp, err := d.c.Create(d.selfKey(), d.config, -1)
|
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
|
||||||
|
resp, err := d.c.Create(ctx, d.selfKey(), d.config, -1)
|
||||||
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure self appears on the server we connected to
|
// ensure self appears on the server we connected to
|
||||||
w := d.c.Watch(d.selfKey(), resp.Node.CreatedIndex)
|
w := d.c.Watch(d.selfKey(), resp.Node.CreatedIndex)
|
||||||
_, err = w.Next()
|
_, err = w.Next(context.Background())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *discovery) checkCluster() (client.Nodes, int, error) {
|
func (d *discovery) checkCluster() (client.Nodes, int, error) {
|
||||||
configKey := path.Join("/", d.cluster, "_config")
|
configKey := path.Join("/", d.cluster, "_config")
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
|
||||||
// find cluster size
|
// find cluster size
|
||||||
resp, err := d.c.Get(path.Join(configKey, "size"))
|
resp, err := d.c.Get(ctx, path.Join(configKey, "size"))
|
||||||
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == client.ErrKeyNoExist {
|
if err == client.ErrKeyNoExist {
|
||||||
return nil, 0, ErrSizeNotFound
|
return nil, 0, ErrSizeNotFound
|
||||||
@ -179,7 +184,9 @@ func (d *discovery) checkCluster() (client.Nodes, int, error) {
|
|||||||
return nil, 0, ErrBadSizeKey
|
return nil, 0, ErrBadSizeKey
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = d.c.Get(d.cluster)
|
ctx, cancel = context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
|
||||||
|
resp, err = d.c.Get(ctx, d.cluster)
|
||||||
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == client.ErrTimeout {
|
if err == client.ErrTimeout {
|
||||||
return d.checkClusterRetry()
|
return d.checkClusterRetry()
|
||||||
@ -254,7 +261,7 @@ func (d *discovery) waitNodes(nodes client.Nodes, size int) (client.Nodes, error
|
|||||||
// wait for others
|
// wait for others
|
||||||
for len(all) < size {
|
for len(all) < size {
|
||||||
log.Printf("discovery: found %d peer(s), waiting for %d more", len(all), size-len(all))
|
log.Printf("discovery: found %d peer(s), waiting for %d more", len(all), size-len(all))
|
||||||
resp, err := w.Next()
|
resp, err := w.Next(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == client.ErrTimeout {
|
if err == client.ErrTimeout {
|
||||||
return d.waitNodesRetry()
|
return d.waitNodesRetry()
|
||||||
|
@ -21,13 +21,13 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/coreos/etcd/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
||||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/jonboulle/clockwork"
|
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/jonboulle/clockwork"
|
||||||
"github.com/coreos/etcd/client"
|
"github.com/coreos/etcd/client"
|
||||||
)
|
)
|
||||||
@ -397,7 +397,7 @@ type clientWithResp struct {
|
|||||||
w client.Watcher
|
w client.Watcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientWithResp) Create(key string, value string, ttl time.Duration) (*client.Response, error) {
|
func (c *clientWithResp) Create(ctx context.Context, key string, value string, ttl time.Duration) (*client.Response, error) {
|
||||||
if len(c.rs) == 0 {
|
if len(c.rs) == 0 {
|
||||||
return &client.Response{}, nil
|
return &client.Response{}, nil
|
||||||
}
|
}
|
||||||
@ -406,7 +406,7 @@ func (c *clientWithResp) Create(key string, value string, ttl time.Duration) (*c
|
|||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientWithResp) Get(key string) (*client.Response, error) {
|
func (c *clientWithResp) Get(ctx context.Context, key string) (*client.Response, error) {
|
||||||
if len(c.rs) == 0 {
|
if len(c.rs) == 0 {
|
||||||
return &client.Response{}, client.ErrKeyNoExist
|
return &client.Response{}, client.ErrKeyNoExist
|
||||||
}
|
}
|
||||||
@ -428,11 +428,11 @@ type clientWithErr struct {
|
|||||||
w client.Watcher
|
w client.Watcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientWithErr) Create(key string, value string, ttl time.Duration) (*client.Response, error) {
|
func (c *clientWithErr) Create(ctx context.Context, key string, value string, ttl time.Duration) (*client.Response, error) {
|
||||||
return &client.Response{}, c.err
|
return &client.Response{}, c.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientWithErr) Get(key string) (*client.Response, error) {
|
func (c *clientWithErr) Get(ctx context.Context, key string) (*client.Response, error) {
|
||||||
return &client.Response{}, c.err
|
return &client.Response{}, c.err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,7 +448,7 @@ type watcherWithResp struct {
|
|||||||
rs []*client.Response
|
rs []*client.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *watcherWithResp) Next() (*client.Response, error) {
|
func (w *watcherWithResp) Next(context.Context) (*client.Response, error) {
|
||||||
if len(w.rs) == 0 {
|
if len(w.rs) == 0 {
|
||||||
return &client.Response{}, nil
|
return &client.Response{}, nil
|
||||||
}
|
}
|
||||||
@ -461,7 +461,7 @@ type watcherWithErr struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *watcherWithErr) Next() (*client.Response, error) {
|
func (w *watcherWithErr) Next(context.Context) (*client.Response, error) {
|
||||||
return &client.Response{}, w.err
|
return &client.Response{}, w.err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,20 +472,20 @@ type clientWithRetry struct {
|
|||||||
failTimes int
|
failTimes int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientWithRetry) Create(key string, value string, ttl time.Duration) (*client.Response, error) {
|
func (c *clientWithRetry) Create(ctx context.Context, key string, value string, ttl time.Duration) (*client.Response, error) {
|
||||||
if c.failCount < c.failTimes {
|
if c.failCount < c.failTimes {
|
||||||
c.failCount++
|
c.failCount++
|
||||||
return nil, client.ErrTimeout
|
return nil, client.ErrTimeout
|
||||||
}
|
}
|
||||||
return c.clientWithResp.Create(key, value, ttl)
|
return c.clientWithResp.Create(ctx, key, value, ttl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientWithRetry) Get(key string) (*client.Response, error) {
|
func (c *clientWithRetry) Get(ctx context.Context, key string) (*client.Response, error) {
|
||||||
if c.failCount < c.failTimes {
|
if c.failCount < c.failTimes {
|
||||||
c.failCount++
|
c.failCount++
|
||||||
return nil, client.ErrTimeout
|
return nil, client.ErrTimeout
|
||||||
}
|
}
|
||||||
return c.clientWithResp.Get(key)
|
return c.clientWithResp.Get(ctx, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// watcherWithRetry will timeout all requests up to failTimes
|
// watcherWithRetry will timeout all requests up to failTimes
|
||||||
@ -495,7 +495,7 @@ type watcherWithRetry struct {
|
|||||||
failTimes int
|
failTimes int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *watcherWithRetry) Next() (*client.Response, error) {
|
func (w *watcherWithRetry) Next(context.Context) (*client.Response, error) {
|
||||||
if w.failCount < w.failTimes {
|
if w.failCount < w.failTimes {
|
||||||
w.failCount++
|
w.failCount++
|
||||||
return nil, client.ErrTimeout
|
return nil, client.ErrTimeout
|
||||||
|
Loading…
x
Reference in New Issue
Block a user