func (client *Client) DecrByAutoTs(key string, value float64, options CreateOptions) (int64, error) {
	conn := client.Pool.Get()
	defer conn.Close()
	args, err := AddCounterArgs(key, -1, value, options)
	if err != nil {
		return -1, err
	}
	return redis.Int64(conn.Do(DECRBY_CMD, args...))
}
Creates a new sample that decrements the latest sample's value with auto timestamp
package redis_timeseries_go
import (
	"strings"
	"time"
	"github.com/gomodule/redigo/redis"
)
var maxConns = 500
func NewClient(addr, name string, authPass *string) *Client {
	addrs := strings.Split(addr, ",")
	var pool ConnPool
	if len(addrs) == 1 {
		pool = NewSingleHostPool(addrs[0], authPass)
	} else {
		pool = NewMultiHostPool(addrs, authPass)
	}
	ret := &Client{
		Pool: pool,
		Name: name,
	}
	return ret
}
func NewClientFromPool(pool *redis.Pool, name string) *Client {
	ret := &Client{
		Pool: pool,
		Name: name,
	}
	return ret
}
func (client *Client) CreateKey(key string, retentionTime time.Duration) (err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	opts := DefaultCreateOptions
	opts.RetentionMSecs = retentionTime
	return client.CreateKeyWithOptions(key, opts)
}
func (client *Client) CreateKeyWithOptions(key string, options CreateOptions) (err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	args := []interface{}{key}
	args, err = options.SerializeSeriesOptions(CREATE_CMD, args)
	if err != nil {
		return
	}
	_, err = conn.Do(CREATE_CMD, args...)
	return err
}
func (client *Client) AlterKeyWithOptions(key string, options CreateOptions) (err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	args := []interface{}{key}
	args, err = options.SerializeSeriesOptions(ALTER_CMD, args)
	if err != nil {
		return
	}
	_, err = conn.Do(ALTER_CMD, args...)
	return err
}
func (client *Client) Add(key string, timestamp int64, value float64) (storedTimestamp int64, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	return redis.Int64(conn.Do(ADD_CMD, key, timestamp, floatToStr(value)))
}
func (client *Client) AddAutoTs(key string, value float64) (storedTimestamp int64, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	return redis.Int64(conn.Do(ADD_CMD, key, "*", floatToStr(value)))
}
func (client *Client) AddWithOptions(key string, timestamp int64, value float64, options CreateOptions) (storedTimestamp int64, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	args := []interface{}{key, timestamp, floatToStr(value)}
	args, err = options.SerializeSeriesOptions(ADD_CMD, args)
	if err != nil {
		return
	}
	return redis.Int64(conn.Do(ADD_CMD, args...))
}
func (client *Client) AddAutoTsWithOptions(key string, value float64, options CreateOptions) (storedTimestamp int64, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	args := []interface{}{key, "*", floatToStr(value)}
	args, err = options.SerializeSeriesOptions(ADD_CMD, args)
	if err != nil {
		return
	}
	return redis.Int64(conn.Do(ADD_CMD, args...))
}
func (client *Client) AddWithRetention(key string, timestamp int64, value float64, duration int64) (storedTimestamp int64, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	options := DefaultCreateOptions
	options.RetentionMSecs = time.Duration(duration)
	return client.AddWithOptions(key, timestamp, value, options)
}
func (client *Client) DeleteSerie(key string) (err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	_, err = conn.Do(DEL_CMD, key)
	return err
}
func (client *Client) DeleteRange(key string, fromTimestamp int64, toTimestamp int64) (totalDeletedSamples int64, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	totalDeletedSamples, err = redis.Int64(conn.Do(TS_DEL_CMD, key, fromTimestamp, toTimestamp))
	return
}
func (client *Client) CreateRule(sourceKey string, aggType AggregationType, bucketSizeMSec uint, destinationKey string) (err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	_, err = conn.Do(CREATERULE_CMD, sourceKey, destinationKey, "AGGREGATION", aggType, bucketSizeMSec)
	return err
}
func (client *Client) DeleteRule(sourceKey string, destinationKey string) (err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	_, err = conn.Do(DELETERULE_CMD, sourceKey, destinationKey)
	return err
}
func (client *Client) Range(key string, fromTimestamp int64, toTimestamp int64) (dataPoints []DataPoint, err error) {
	return client.RangeWithOptions(key, fromTimestamp, toTimestamp, DefaultRangeOptions)
}
func (client *Client) AggRange(key string, fromTimestamp int64, toTimestamp int64, aggType AggregationType,
	bucketSizeSec int) (dataPoints []DataPoint, err error) {
	rangeOptions := NewRangeOptions()
	rangeOptions = rangeOptions.SetAggregation(aggType, bucketSizeSec)
	return client.RangeWithOptions(key, fromTimestamp, toTimestamp, *rangeOptions)
}
func (client *Client) RangeWithOptions(key string, fromTimestamp int64, toTimestamp int64, rangeOptions RangeOptions) (dataPoints []DataPoint, err error) {
	return client.rangeWithOptions(RANGE_CMD, key, fromTimestamp, toTimestamp, rangeOptions)
}
func (client *Client) ReverseRangeWithOptions(key string, fromTimestamp int64, toTimestamp int64, rangeOptions RangeOptions) (dataPoints []DataPoint, err error) {
	return client.rangeWithOptions(REVRANGE_CMD, key, fromTimestamp, toTimestamp, rangeOptions)
}
func (client *Client) rangeWithOptions(command string, key string, fromTimestamp int64, toTimestamp int64, rangeOptions RangeOptions) (dataPoints []DataPoint, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	var reply interface{}
	args := createRangeCmdArguments(key, fromTimestamp, toTimestamp, rangeOptions)
	reply, err = conn.Do(command, args...)
	if err != nil {
		return
	}
	dataPoints, err = ParseDataPoints(reply)
	return
}
func (client *Client) AggMultiRange(fromTimestamp int64, toTimestamp int64, aggType AggregationType,
	bucketSizeSec int, filters ...string) (ranges []Range, err error) {
	mrangeOptions := NewMultiRangeOptions()
	mrangeOptions = mrangeOptions.SetAggregation(aggType, bucketSizeSec)
	return client.MultiRangeWithOptions(fromTimestamp, toTimestamp, *mrangeOptions, filters...)
}
func (client *Client) MultiRangeWithOptions(fromTimestamp int64, toTimestamp int64, mrangeOptions MultiRangeOptions, filters ...string) (ranges []Range, err error) {
	return client.multiRangeWithOptions(MRANGE_CMD, fromTimestamp, toTimestamp, mrangeOptions, filters)
}
func (client *Client) MultiReverseRangeWithOptions(fromTimestamp int64, toTimestamp int64, mrangeOptions MultiRangeOptions, filters ...string) (ranges []Range, err error) {
	return client.multiRangeWithOptions(MREVRANGE_CMD, fromTimestamp, toTimestamp, mrangeOptions, filters)
}
func (client *Client) multiRangeWithOptions(cmd string, fromTimestamp int64, toTimestamp int64, mrangeOptions MultiRangeOptions, filters []string) (ranges []Range, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	var reply interface{}
	args := createMultiRangeCmdArguments(fromTimestamp, toTimestamp, mrangeOptions, filters)
	reply, err = conn.Do(cmd, args...)
	if err != nil {
		return
	}
	ranges, err = ParseRanges(reply)
	return
}
func (client *Client) Get(key string) (dataPoint *DataPoint,
	err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	resp, err := conn.Do(GET_CMD, key)
	if err != nil {
		return nil, err
	}
	dataPoint, err = ParseDataPoint(resp)
	return
}
func (client *Client) MultiGet(filters ...string) (ranges []Range, err error) {
	return client.MultiGetWithOptions(DefaultMultiGetOptions, filters...)
}
func (client *Client) MultiGetWithOptions(multiGetOptions MultiGetOptions, filters ...string) (ranges []Range, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	var reply interface{}
	if len(filters) == 0 {
		return
	}
	args := createMultiGetCmdArguments(multiGetOptions, filters)
	reply, err = conn.Do(MGET_CMD, args...)
	if err != nil {
		return
	}
	ranges, err = ParseRangesSingleDataPoint(reply)
	return
}
func (client *Client) Info(key string) (res KeyInfo, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	res, err = ParseInfo(conn.Do(INFO_CMD, key))
	return res, err
}
func (client *Client) QueryIndex(filters ...string) (keys []string, err error) {
	conn := client.Pool.Get()
	defer conn.Close()
	if len(filters) == 0 {
		return
	}
	args := redis.Args{}
	for _, filter := range filters {
		args = args.Add(filter)
	}
	return redis.Strings(conn.Do(QUERYINDEX_CMD, args...))
}
func (client *Client) IncrBy(key string, timestamp int64, value float64, options CreateOptions) (int64, error) {
	conn := client.Pool.Get()
	defer conn.Close()
	args, err := AddCounterArgs(key, timestamp, value, options)
	if err != nil {
		return -1, err
	}
	return redis.Int64(conn.Do(INCRBY_CMD, args...))
}
func (client *Client) IncrByAutoTs(key string, value float64, options CreateOptions) (int64, error) {
	conn := client.Pool.Get()
	defer conn.Close()
	args, err := AddCounterArgs(key, -1, value, options)
	if err != nil {
		return -1, err
	}
	return redis.Int64(conn.Do(INCRBY_CMD, args...))
}
func (client *Client) DecrBy(key string, timestamp int64, value float64, options CreateOptions) (int64, error) {
	conn := client.Pool.Get()
	defer conn.Close()
	args, err := AddCounterArgs(key, timestamp, value, options)
	if err != nil {
		return -1, err
	}
	return redis.Int64(conn.Do(DECRBY_CMD, args...))
}