package zoo import ( "sync" "time" "github.com/samuel/go-zookeeper/zk" ) const ( defaultSessionTimeout = 60 * time.Second currentPath = "." ) var zkSessionTimeout = defaultSessionTimeout type client2 struct { *zk.Conn path string done chan struct{} // signal chan, closes when the underlying connection terminates stopOnce sync.Once } func connect2(hosts []string, path string) (*client2, error) { c, ev, err := zk.Connect(hosts, zkSessionTimeout) if err != nil { return nil, err } done := make(chan struct{}) go func() { // close the 'done' chan when the zk event chan closes (signals termination of zk connection) defer close(done) for { if _, ok := <-ev; !ok { return } } }() return &client2{ Conn: c, path: path, done: done, }, nil } func (c *client2) stopped() <-chan struct{} { return c.done } func (c *client2) stop() { c.stopOnce.Do(c.Close) } func (c *client2) data(path string) (data []byte, err error) { data, _, err = c.Get(path) return } func (c *client2) watchChildren(path string) (string, <-chan []string, <-chan error) { errCh := make(chan error, 1) snap := make(chan []string) watchPath := c.path if path != "" && path != currentPath { watchPath = watchPath + path } go func() { defer close(errCh) for { children, _, ev, err := c.ChildrenW(watchPath) if err != nil { errCh <- err return } select { case snap <- children: case <-c.done: return } e := <-ev // wait for the next watch-related event if e.Err != nil { errCh <- e.Err return } } }() return watchPath, snap, errCh }