Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to get error when watch fail in clientv3? #6699

Closed
xiaoyulei opened this issue Oct 21, 2016 · 5 comments
Closed

How to get error when watch fail in clientv3? #6699

xiaoyulei opened this issue Oct 21, 2016 · 5 comments

Comments

@xiaoyulei
Copy link
Contributor

In clientv3, Watch just close channel when fail. Is there anyway to get the fail error to know the reason?

@xiang90
Copy link
Contributor

xiang90 commented Oct 21, 2016

@YuleiXiao watch will keep retry forever internally until user cancels it. It makes sense for most of the use cases. Users cannot do much about the errors anyway. So now we do not emit intermediate errors. But for logging or other debugging purpose, people might still want to see errors. I discussed with @heyitsanthony before. Probably we should give users errors.

@yudai
Copy link
Contributor

yudai commented Oct 21, 2016

When you want to detect errors while watching, you probably need to use a technique that using concurrency.Session along with Watch(), as suggested in #5985.

@yudai
Copy link
Contributor

yudai commented Oct 21, 2016

Here's a snippet that I use when I want detect errors. Note that Watch() can return a closed channel, however, once it returns an open channel, it will be closed only by context cancelation as @xiang90 mentioned.

func myWatch(client *clientv3.Client, ctx context.Context) error {
  session, err := concurrency.NewSession(
    client, concurrency.WithTTL(someTTL),
  ) // this can hang up, but anyway... #6681
  if err != nil {
    return errors.Wrapf(err, "failed to establish a session to the etcd")
  }

  watchCtx, watchCancel := context.WithCancel(ctx)
  watchRet := make(chan error, 1)
  go func() {
    watchRet <- func() error { // wrap by a func to make sure watchRet gets item
      rch := client.Watch(
        watchCtx, "/your/prefix", clientv3.WithPrefix(),
      )

      for wresp := range rch {
        err := wresp.Err()
        if err != nil {
          return err
        }
        for _, ev := range wresp.Events {
          err := doSomething(ev)
          if err != nil {
            return err
          }
        }
      }

      return nil
    }()
  }()

  select {
  case <-session.Done(): // closed by etcd
    watchCancel()
    //<-watchRet #6651
    return fmt.Errorf("connection to the etcd closed")
  case <-ctx.Done(): // user cancel
    //<-watchRet 6651
    return ctx.Err()
  case err := <-watchRet: // error in watcher
    //session.Close() # 6681
    return err
  }
}

@xiaoyulei
Copy link
Contributor Author

@yudai Thanks, there is Err() in WatchChan, that is what I want.

@xiang90
Copy link
Contributor

xiang90 commented Oct 26, 2016

@YuleiXiao OK. Err() returns critical error that terminates watcher. Good to know it is what you were looking for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants