Example #1
0
func (e *Election) observe(ctx context.Context, ch chan<- v3.GetResponse) {
	client := e.session.Client()

	defer close(ch)
	for {
		resp, err := client.Get(ctx, e.keyPrefix, v3.WithFirstCreate()...)
		if err != nil {
			return
		}

		var kv *mvccpb.KeyValue

		cctx, cancel := context.WithCancel(ctx)
		if len(resp.Kvs) == 0 {
			// wait for first key put on prefix
			opts := []v3.OpOption{v3.WithRev(resp.Header.Revision), v3.WithPrefix()}
			wch := client.Watch(cctx, e.keyPrefix, opts...)

			for kv == nil {
				wr, ok := <-wch
				if !ok || wr.Err() != nil {
					cancel()
					return
				}
				// only accept PUTs; a DELETE will make observe() spin
				for _, ev := range wr.Events {
					if ev.Type == mvccpb.PUT {
						kv = ev.Kv
						break
					}
				}
			}
		} else {
			kv = resp.Kvs[0]
		}

		wch := client.Watch(cctx, string(kv.Key), v3.WithRev(kv.ModRevision))
		keyDeleted := false
		for !keyDeleted {
			wr, ok := <-wch
			if !ok {
				return
			}
			for _, ev := range wr.Events {
				if ev.Type == mvccpb.DELETE {
					keyDeleted = true
					break
				}
				resp.Header = &wr.Header
				resp.Kvs = []*mvccpb.KeyValue{ev.Kv}
				select {
				case ch <- *resp:
				case <-cctx.Done():
					return
				}
			}
		}
		cancel()
	}
}
Example #2
0
// Leader returns the leader value for the current election.
func (e *Election) Leader() (string, error) {
	resp, err := e.kv.Get(e.ctx, e.keyPrefix, v3.WithFirstCreate()...)
	if err != nil {
		return "", err
	} else if len(resp.Kvs) == 0 {
		// no leader currently elected
		return "", etcdserver.ErrNoLeader
	}
	return string(resp.Kvs[0].Value), nil
}
Example #3
0
// Leader returns the leader value for the current election.
func (e *Election) Leader(ctx context.Context) (string, error) {
	resp, err := e.client.Get(ctx, e.keyPrefix, v3.WithFirstCreate()...)
	if err != nil {
		return "", err
	} else if len(resp.Kvs) == 0 {
		// no leader currently elected
		return "", ErrElectionNoLeader
	}
	return string(resp.Kvs[0].Value), nil
}
Example #4
0
// Wait waits for a leader to be elected, returning the leader value.
func (e *Election) Wait() (string, error) {
	resp, err := e.kv.Get(e.ctx, e.keyPrefix, v3.WithFirstCreate()...)
	if err != nil {
		return "", err
	} else if len(resp.Kvs) != 0 {
		// leader already exists
		return string(resp.Kvs[0].Value), nil
	}
	_, err = WaitPrefixEvents(
		e.client,
		e.keyPrefix,
		resp.Header.Revision,
		[]storagepb.Event_EventType{storagepb.PUT})
	if err != nil {
		return "", err
	}
	return e.Wait()
}