Documentation ¶
Overview ¶
Package ezk is an enhanced Zookeeper client. It uses the connection and underlying operations from https://github.com/samuel/go-zookeeper/zk in conjunction with automatic retry of operations via the https://github.com/betable/retry library.
ABOUT THE CHROOT PREFIX, ABSOLUTE PATHS, AND RELATIVE PATHS =========================================================== Examples of Chroot prefixes commonly used are "/production/", "/staging/", and "/devtest/". These prefixes let one multitask the Zookeeper cluster for different responsibilities without incurring crosstalk between applications. The Chroot prefix is implicitly prepended to any relative path supplied to an ezk API call. Our (enforced) zookeeper path convention for the ClientConfig.Chroot string allows us to distinguish between chroot-ed paths and non-chroot paths, and between absolute versus relative paths as follows: * the Chroot prefix must always start with a forward slash. A single '/' alone is a valid Chroot prefix. If the prefix is longer than one character, the Chroot prefix must also end with a '/' as well--in this case the prefix will contain exactly two '/' slash characters; one at the beginning and one at the end. A Chroot prefix therefore names either zero or one znodes. For example: "/prod/", "/staging/", and "/devtest/" are all legal Chroot strings. Counter-examples: "/prod" is not a legal Chroot value, nor is "prod/", nor is "prod". User code can distinguish Chroot prefixes by checking whether the first byte of the string is '/' or not. See the IsAbsolutePath() and RemoveChroot() helper functions. * All paths that are intended to be relative to the Chroot prefix must *not* start with a forward slash and must not end with a forward slash; they are like relative paths in Unix. So legal examples of relative paths: "myservice/config/my-servers", "piper", or "timeseries", or "timeseries/config". The requirement forbidding the trailing '/' is enforced on the Zookeeper server side. * The ezk library will form the full path (spoken on the wire to the Zookeeper) by a simple concatenation of Chroot + relative path. * The helper function RemoveChroot(path) will detect and automatically remove any chroot prefix from path, and returns a relative path. It will leave untouched already relative paths. * Important: when receiving watch events on channels from the github.com/samuel/go-zookeeper/zk library, they are of the following Event type. See the notes on the Path field below. type Event struct { Type EventType State State // Path is for non-session events; it is // the (absolute, Chroot-prefixed) path // of the watched node. [1] Path string Err error Server string // For connection events } Note [1] that this Path is absolute, it includes the Chroot prefix. Users should call RemoveChroot() function as needed before using the Event.Path field if they require a relative path.
Index ¶
- func ChompSlash(path string) string
- func DefaultRetry(op, path string, f func() error)
- func IsAbsolutePath(path string) bool
- func RemoveChroot(path string) string
- type Client
- func (z *Client) Children(path string) (c []string, s *zk.Stat, err error)
- func (z *Client) ChildrenW(path string) (c []string, s *zk.Stat, ch <-chan zk.Event, err error)
- func (z *Client) Close()
- func (z *Client) Connect() error
- func (z *Client) Create(path string, data []byte, flags int32, acl []zk.ACL) (s string, err error)
- func (z *Client) CreateDir(path string, acl []zk.ACL) error
- func (z *Client) CreateNode(path string) error
- func (z *Client) CreateProtectedEphemeralSequential(path string, data []byte, acl []zk.ACL) (string, error)
- func (z *Client) Delete(path string, version int32) (err error)
- func (z *Client) DeleteNode(path string) error
- func (z *Client) DeleteNodeRecursively(path string) error
- func (z *Client) Exists(path string) (ok bool, s *zk.Stat, err error)
- func (z *Client) ExistsW(path string) (ok bool, s *zk.Stat, ch <-chan zk.Event, err error)
- func (z *Client) Get(path string) (d []byte, s *zk.Stat, err error)
- func (z *Client) GetACL(path string) (a []zk.ACL, s *zk.Stat, err error)
- func (z *Client) GetW(path string) (d []byte, s *zk.Stat, ch <-chan zk.Event, err error)
- func (z *Client) SafeGet(path string) ([]byte, *zk.Stat, error)
- func (z *Client) SafeSet(path string, data []byte, version int32, acl []zk.ACL) (*zk.Stat, error)
- func (z *Client) Set(path string, data []byte, version int32) (s *zk.Stat, err error)
- func (z *Client) SetACL(path string, acl []zk.ACL, version int32) (s *zk.Stat, err error)
- func (z *Client) Sync(path string) (s string, err error)
- type ClientConfig
- type Retry
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ChompSlash ¶
ChompSlash removes any trailing single '/' from path. It only checks the very last character.
func DefaultRetry ¶
The DefaultRetry function will retry four times if the first Zookeeper call fails, after sleeping in turn: 0ms, 100ms, 500ms and 1500ms.
func IsAbsolutePath ¶
IsAbsolutePath() checks to see if the path starts with a Chroot element by checking if the first byte is a '/' or not.
func RemoveChroot ¶
RemoveChroot(path) will detect and automatically remove any chroot prefix, and return a relative path.
Examples: "/mybase/myservice/config" -> "myservice/config"
"/myroot/alist" -> "alist" "/hello/" -> "" "/poorlyFormed" -> "" ## properly should have a trailling slash "relative/path/unchanged" -> "relative/path/unchanged"
RemoveChroot will leave untouched any already relative paths. Note that this returned relative path may be the empty string "" if path consists of one element "/chroot/" alone, for example.
Types ¶
type Client ¶
type Client struct { // The configuration for the client. Cfg ClientConfig // The underlying github.com/samuel/go-zookeeper/zk connection. Conn *zk.Conn // WatchCh will be nil until Connect returns without error. // Watches that fire over the Zookeeper connection will be // received on WatchCh. WatchCh <-chan zk.Event }
Client is a wrapper over github.com/samuel/go-zookeeper/zk that retries all but one of its operations according to the ClientConfig.Retry function. The one exception is for CreateProtectedEphemeralSequential(); it is not retried automatically.
Example ¶
In the example code, the goal is to set the value newURL into the node /chroot/service-name/config/server-url-list
newURL := "http://my-new-url.org:343/hello/enhanced-zookeeper-client" base := "/chroot/" path := "service-name/config/server-url-list" zkCfg := ClientConfig{ Servers: []string{"127.0.0.1:2181"}, Acl: zook.WorldACL(zook.PermAll), Chroot: base, SessionTimeout: 10 * time.Second, } zk := NewClient(zkCfg) err := zk.Connect() if err != nil { panic(err) } defer zk.Close() err = zk.CreateDir(path, nil) if err != nil { panic(err) } err = zk.DeleteNode(path) // delete any old value if err != nil { panic(err) } err = zk.CreateNode(path) if err != nil { panic(err) } _, err = zk.Set(path, []byte(newURL), -1) if err != nil { panic(err) }
Output:
func NewClient ¶
func NewClient(cfg ClientConfig) *Client
NewClient creates a new ezk.Client. If the cfg.SessionTimout is set to 0 a default value of 10 seconds will be used. If cfg.Retry is nil then the DefaultRetry function will be used. If cfg.Acl is length 0 then zk.WorldACL(zk.PermAll) will be used.
func (*Client) Children ¶
Children returns the children of a znode. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) ChildrenW ¶
ChildrenW returns the children of a znode and sets a watch. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) Close ¶
func (z *Client) Close()
Close closes the connection to the Zookeeper server.
func (*Client) Connect ¶
Connect connects to a Zookeeper server. Upon success it sets the z.WatchCh and z.Conn and returns nil. If an error is returned then z.WatchCh and z.Conn will not be set. Connect() will typically only be needed once, but can be called again if need be. Upon successful connection to Zookeeper, we will attempt to create the z.Cfg.Chroot node. No error will be returned if this attempt fails, as commonly it may already exist.
func (*Client) Create ¶
Create creates a znode with a content. If acl is nil then the z.Cfg.Acl set will be applied to the new znode. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) CreateDir ¶
CreateDir is a helper method that creates a path of empty znodes if they do not exist. It acts like os.MkdirAll or mkdir -p in that it will create a series of nested directories if the path supplies them. It won't fail if some or all of these already exist. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) CreateNode ¶
A convenience version of Create, CreateNode supplies empty data, 0 flags, and the default z.Cfg.Acl list to a z.Create() call. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) CreateProtectedEphemeralSequential ¶
func (z *Client) CreateProtectedEphemeralSequential(path string, data []byte, acl []zk.ACL) (string, error)
CreateProtectedEphemeralSequential creates a sequential ephemeral znode. z.Cfg.Chroot will be prepended to a relative path. The call will be NOT be retried.
func (*Client) Delete ¶
Delete deletes a znode. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) DeleteNode ¶
A convenience version of Delete, DeleteNode deletes a znode, using version -1 to delete any version. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) DeleteNodeRecursively ¶
A convenience version of Delete, DeleteNodeRecursively deletes a znode and any of its children, using version -1 to delete any version. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) Exists ¶
Exists checks if a znode exists. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) ExistsW ¶
ExistsW returns if a znode exists and sets a watch. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) Get ¶
Get returns the contents of a znode. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) GetACL ¶
GetACL returns the ACL for a znode. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) GetW ¶
GetW returns the contents of a znode and sets a watch. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) SafeGet ¶
SafeGet is a helper method that syncs Zookeeper and return the content of a znode. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) SafeSet ¶
SafeSet is a helper method that writes a znode creating it first if it does not exists. It will sync the Zookeeper before checking if the node exists. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
func (*Client) Set ¶
Set writes content in an existent znode. z.Cfg.Chroot will be prepended to a relative path. The call will be retried.
type ClientConfig ¶
type ClientConfig struct { // The Chroot directory will be prepended to all paths Chroot string // The set of ACLs used by defeault when // calling Client.Create(), if the formal // parameter acl in Create() is length 0. Acl []zk.ACL // The URLs of the zookeepers to attempt to connect to. Servers []string // SessionTimeout defaults to 10 seconds if not // otherwise set. SessionTimeout time.Duration // The Retry function determines how many times // and how often we retry our Zookeeper operations // before failing. See DefaultRetry() which is // used if this is not otherwise set. Retry Retry }
ClientConfig is used to configure a Client; pass it to NewClient().