func (q *PriorityQueue) Dequeue() (string, error) {
	resp, err := q.client.Get(q.ctx, q.key, v3.WithFirstKey()...)
	if err != nil {
		return "", err
	}
	kv, err := claimFirstKey(q.client, resp.Kvs)
	if err != nil {
		return "", err
	} else if kv != nil {
		return string(kv.Value), nil
	} else if resp.More {
		return q.Dequeue()
	}
	ev, err := WaitPrefixEvents(
		q.client,
		q.key,
		resp.Header.Revision,
		[]mvccpb.Event_EventType{mvccpb.PUT})
	if err != nil {
		return "", err
	}
	ok, err := deleteRevKey(q.client, string(ev.Kv.Key), ev.Kv.ModRevision)
	if err != nil {
		return "", err
	} else if !ok {
		return q.Dequeue()
	}
	return string(ev.Kv.Value), err
}
Dequeue returns Enqueue()'d items in FIFO order. If the
queue is empty, Dequeue blocks until items are available.
package recipe
import (
	"fmt"
	v3 "github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/mvcc/mvccpb"
	"golang.org/x/net/context"
)
type PriorityQueue struct {
	client *v3.Client
	ctx    context.Context
	key    string
}
func NewPriorityQueue(client *v3.Client, key string) *PriorityQueue {
	return &PriorityQueue{client, context.TODO(), key + "/"}
}
func (q *PriorityQueue) Enqueue(val string, pr uint16) error {
	prefix := fmt.Sprintf("%s%05d", q.key, pr)
	_, err := newSequentialKV(q.client, prefix, val)
	return err
}