mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
client: further clarify external interfaces
This commit is contained in:
parent
17c6f21d68
commit
58af26736c
@ -1,96 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
||||
)
|
||||
|
||||
type HTTPClient interface {
|
||||
Do(context.Context, HTTPAction) (*http.Response, []byte, error)
|
||||
Sync() error
|
||||
}
|
||||
|
||||
type httpActionDo interface {
|
||||
Do(context.Context, HTTPAction) (*http.Response, []byte, error)
|
||||
}
|
||||
|
||||
type HTTPAction interface {
|
||||
HTTPRequest(url.URL) *http.Request
|
||||
}
|
||||
|
||||
// CancelableTransport mimics http.Transport to provide an interface which can be
|
||||
// substituted for testing (since the RoundTripper interface alone does not
|
||||
// require the CancelRequest method)
|
||||
type CancelableTransport interface {
|
||||
http.RoundTripper
|
||||
CancelRequest(req *http.Request)
|
||||
}
|
||||
|
||||
func NewHTTPClient(tr CancelableTransport, eps []string) (*httpClusterClient, error) {
|
||||
c := httpClusterClient{
|
||||
transport: tr,
|
||||
endpoints: make([]httpActionDo, len(eps)),
|
||||
}
|
||||
|
||||
for i, ep := range eps {
|
||||
u, err := url.Parse(ep)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.endpoints[i] = &httpClient{
|
||||
transport: tr,
|
||||
endpoint: *u,
|
||||
}
|
||||
}
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
type httpClusterClient struct {
|
||||
transport CancelableTransport
|
||||
endpoints []httpActionDo
|
||||
}
|
||||
|
||||
func (c *httpClusterClient) Do(ctx context.Context, act HTTPAction) (*http.Response, []byte, error) {
|
||||
//TODO(bcwaldon): introduce retry logic so all endpoints are attempted
|
||||
return c.endpoints[0].Do(ctx, act)
|
||||
}
|
||||
|
||||
func (c *httpClusterClient) Sync(ctx context.Context) error {
|
||||
mAPI := NewMembersAPI(c)
|
||||
ms, err := mAPI.List(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eps := make([]string, 0)
|
||||
for _, m := range ms {
|
||||
eps = append(eps, m.ClientURLs...)
|
||||
}
|
||||
nc, err := NewHTTPClient(c.transport, eps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*c = *nc
|
||||
return nil
|
||||
}
|
@ -30,6 +30,82 @@ var (
|
||||
DefaultRequestTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
type SyncableHTTPClient interface {
|
||||
HTTPClient
|
||||
Sync(context.Context) error
|
||||
}
|
||||
|
||||
type HTTPClient interface {
|
||||
Do(context.Context, HTTPAction) (*http.Response, []byte, error)
|
||||
}
|
||||
|
||||
type HTTPAction interface {
|
||||
HTTPRequest(url.URL) *http.Request
|
||||
}
|
||||
|
||||
// CancelableTransport mimics http.Transport to provide an interface which can be
|
||||
// substituted for testing (since the RoundTripper interface alone does not
|
||||
// require the CancelRequest method)
|
||||
type CancelableTransport interface {
|
||||
http.RoundTripper
|
||||
CancelRequest(req *http.Request)
|
||||
}
|
||||
|
||||
func NewHTTPClient(tr CancelableTransport, eps []string) (SyncableHTTPClient, error) {
|
||||
return newHTTPClusterClient(tr, eps)
|
||||
}
|
||||
|
||||
func newHTTPClusterClient(tr CancelableTransport, eps []string) (*httpClusterClient, error) {
|
||||
c := httpClusterClient{
|
||||
transport: tr,
|
||||
endpoints: make([]HTTPClient, len(eps)),
|
||||
}
|
||||
|
||||
for i, ep := range eps {
|
||||
u, err := url.Parse(ep)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.endpoints[i] = &httpClient{
|
||||
transport: tr,
|
||||
endpoint: *u,
|
||||
}
|
||||
}
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
type httpClusterClient struct {
|
||||
transport CancelableTransport
|
||||
endpoints []HTTPClient
|
||||
}
|
||||
|
||||
func (c *httpClusterClient) Do(ctx context.Context, act HTTPAction) (*http.Response, []byte, error) {
|
||||
//TODO(bcwaldon): introduce retry logic so all endpoints are attempted
|
||||
return c.endpoints[0].Do(ctx, act)
|
||||
}
|
||||
|
||||
func (c *httpClusterClient) Sync(ctx context.Context) error {
|
||||
mAPI := NewMembersAPI(c)
|
||||
ms, err := mAPI.List(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eps := make([]string, 0)
|
||||
for _, m := range ms {
|
||||
eps = append(eps, m.ClientURLs...)
|
||||
}
|
||||
nc, err := newHTTPClusterClient(c.transport, eps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*c = *nc
|
||||
return nil
|
||||
}
|
||||
|
||||
type roundTripResponse struct {
|
||||
resp *http.Response
|
||||
err error
|
||||
|
@ -41,14 +41,14 @@ var (
|
||||
ErrKeyExists = errors.New("client: key already exists")
|
||||
)
|
||||
|
||||
func NewKeysAPI(c httpActionDo) KeysAPI {
|
||||
func NewKeysAPI(c HTTPClient) KeysAPI {
|
||||
return &httpKeysAPI{
|
||||
client: c,
|
||||
prefix: DefaultV2KeysPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDiscoveryKeysAPI(c httpActionDo) KeysAPI {
|
||||
func NewDiscoveryKeysAPI(c HTTPClient) KeysAPI {
|
||||
return &httpKeysAPI{
|
||||
client: c,
|
||||
prefix: "",
|
||||
@ -87,7 +87,7 @@ func (n *Node) String() string {
|
||||
}
|
||||
|
||||
type httpKeysAPI struct {
|
||||
client httpActionDo
|
||||
client HTTPClient
|
||||
prefix string
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ func (k *httpKeysAPI) RecursiveWatch(key string, idx uint64) Watcher {
|
||||
}
|
||||
|
||||
type httpWatcher struct {
|
||||
client httpActionDo
|
||||
client HTTPClient
|
||||
nextWait waitAction
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ var (
|
||||
DefaultV2MembersPrefix = "/v2/members"
|
||||
)
|
||||
|
||||
func NewMembersAPI(c httpActionDo) MembersAPI {
|
||||
func NewMembersAPI(c HTTPClient) MembersAPI {
|
||||
return &httpMembersAPI{
|
||||
client: c,
|
||||
}
|
||||
@ -46,7 +46,7 @@ type MembersAPI interface {
|
||||
}
|
||||
|
||||
type httpMembersAPI struct {
|
||||
client httpActionDo
|
||||
client HTTPClient
|
||||
}
|
||||
|
||||
func (m *httpMembersAPI) List(ctx context.Context) ([]httptypes.Member, error) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user