func (c *RedisClient) Qlen(qname string) (int, error) {
	return redis.Int(c.conn.Do("QLEN", qname))
}
Qlen returns the length of a given queue
package disque
import (
	"errors"
	"fmt"
	"log"
	"net"
	"strconv"
	"time"
	"github.com/garyburd/redigo/redis"
)
type Job struct {
	Queue string
	Data []byte
	id string
}
func (j Job) Id() string {
	return j.id
}
type AddRequest struct {
	Job Job
	Timeout time.Duration
	Replicate int
	Delay time.Duration
	Retry time.Duration
	TTL time.Duration
	Maxlen int
	Async bool
}
type HelloResponse struct {
	NodeId string
	Nodes  nodeList
}
type Client interface {
	Add(AddRequest) (string, error)
	AddMulti([]AddRequest) ([]string, error)
	Get(timeout time.Duration, queues ...string) (Job, error)
	GetMulti(count int, timeout time.Duration, queues ...string) ([]Job, error)
	Ack(jobIds ...string) error
	FastAck(jobIds ...string) error
	Qlen(qname string) (int, error)
	Hello() (HelloResponse, error)
	Close() error
}
type RedisClient struct {
	conn redis.Conn
	node Node
}
func (c *RedisClient) Close() error {
	return c.conn.Close()
}
func (c *RedisClient) Add(r AddRequest) (string, error) {
	id, err := redis.String(c.conn.Do("ADDJOB", addArgs(r)...))
	if err != nil {
		return "", errors.New("disque: could not add job: " + err.Error())
	}
	return id, nil
}
func (c *RedisClient) AddMulti(rs []AddRequest) ([]string, error) {
	for _, r := range rs {
		if err := c.conn.Send("ADDJOB", addArgs(r)...); err != nil {
			return nil, err
		}
	}
	replies, err := redis.Values(c.conn.Do(""))
	ids := make([]string, len(replies))
	for i, val := range replies {
		if id, ok := val.(string); ok {
			ids[i] = id
		}
	}
	return ids, err
}
func addArgs(r AddRequest) redis.Args {
	args := redis.Args{r.Job.Queue, r.Job.Data, int(r.Timeout / time.Millisecond)}
	if r.Replicate > 0 {
		args = args.Add("REPLICATE", r.Replicate)
	}
	if r.Delay > 0 {
		args = args.Add("DELAY", int64(r.Delay.Seconds()))
	}
	if r.Retry > 0 {
		args = args.Add("RETRY", int64(r.Retry.Seconds()))
	}
	if r.TTL > 0 {
		args = args.Add("TTL", int64(r.TTL.Seconds()))
	}
	if r.Maxlen > 0 {
		args = args.Add("MAXLEN", r.Maxlen)
	}
	if r.Async {
		args = args.Add("ASYNC")
	}
	return args
}
func (c *RedisClient) Get(timeout time.Duration, queues ...string) (Job, error) {
	ret, err := c.GetMulti(0, timeout, queues...)
	if err != nil {
		return Job{}, err
	}
	if ret == nil || len(ret) == 0 {
		return Job{}, errors.New("disque: no jobs returned")
	}
	return ret[0], nil
}
func (c *RedisClient) GetMulti(count int, timeout time.Duration, queues ...string) ([]Job, error) {
	if len(queues) == 0 {
		return nil, errors.New("disque: no queues specified")
	}
	if count < 0 {
		return nil, fmt.Errorf("disque: invalid count %d", count)
	}
	args := redis.Args{}
	if timeout > 0 {
		args = args.Add("TIMEOUT", int64(timeout/time.Millisecond))
	}
	if count > 0 {
		args = args.Add("COUNT", count)
	}
	args = args.Add("FROM")
	args = args.AddFlat(queues)
	vals, err := redis.Values(c.conn.Do("GETJOB", args...))
	if err != nil {
		return nil, fmt.Errorf("disque: could not get jobs: %s", err)
	}
	ret := make([]Job, 0, len(vals))
	for _, v := range vals {
		if arr, ok := v.([]interface{}); ok {
			ret = append(ret, Job{
				Queue: string(arr[0].([]byte)),
				id:    string(arr[1].([]byte)),
				Data:  arr[2].([]byte),
			})
		}
	}
	return ret, nil
}
func (c *RedisClient) Ack(jobIds ...string) error {
	args := make(redis.Args, 0, len(jobIds))
	args = args.AddFlat(jobIds)
	if _, err := c.conn.Do("ACKJOB", args...); err != nil {
		return fmt.Errorf("disque: error sending ACK: %s", err)
	}
	return nil
}
func (c *RedisClient) FastAck(jobIds ...string) error {
	args := make(redis.Args, 0, len(jobIds))
	args = args.AddFlat(jobIds)
	if _, err := c.conn.Do("FASTACK", args...); err != nil {
		return fmt.Errorf("disque: error sending ACK: %s", err)
	}
	return nil
}