mirror of https://github.com/go-redis/redis.git
feature: add XINFO STREAM support
This commit is contained in:
parent
2b9cfd3cc4
commit
a2b0227421
145
command.go
145
command.go
|
@ -1081,34 +1081,43 @@ func (cmd *XMessageSliceCmd) readReply(rd *proto.Reader) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readXMessage(rd *proto.Reader) (XMessage, error) {
|
||||||
|
n, err := rd.ReadArrayLen()
|
||||||
|
if err != nil {
|
||||||
|
return XMessage{}, err
|
||||||
|
}
|
||||||
|
if n != 2 {
|
||||||
|
return XMessage{}, fmt.Errorf("got %d, wanted 2", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := rd.ReadString()
|
||||||
|
if err != nil {
|
||||||
|
return XMessage{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var values map[string]interface{}
|
||||||
|
|
||||||
|
v, err := rd.ReadArrayReply(stringInterfaceMapParser)
|
||||||
|
if err != nil {
|
||||||
|
if err != proto.Nil {
|
||||||
|
return XMessage{}, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
values = v.(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
return XMessage{
|
||||||
|
ID: id,
|
||||||
|
Values: values,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// xMessageSliceParser implements proto.MultiBulkParse.
|
// xMessageSliceParser implements proto.MultiBulkParse.
|
||||||
func xMessageSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
|
func xMessageSliceParser(rd *proto.Reader, n int64) (interface{}, error) {
|
||||||
msgs := make([]XMessage, n)
|
msgs := make([]XMessage, n)
|
||||||
for i := 0; i < len(msgs); i++ {
|
for i := int64(0); i < n; i++ {
|
||||||
i := i
|
var err error
|
||||||
_, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) {
|
msgs[i], err = readXMessage(rd)
|
||||||
id, err := rd.ReadString()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var values map[string]interface{}
|
|
||||||
|
|
||||||
v, err := rd.ReadArrayReply(stringInterfaceMapParser)
|
|
||||||
if err != nil {
|
|
||||||
if err != proto.Nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
values = v.(map[string]interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
msgs[i] = XMessage{
|
|
||||||
ID: id,
|
|
||||||
Values: values,
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1493,6 +1502,92 @@ func readXGroupInfo(rd *proto.Reader) (XInfoGroup, error) {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type XInfoStreamCmd struct {
|
||||||
|
baseCmd
|
||||||
|
val *XInfoStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type XInfoStream struct {
|
||||||
|
Length int64
|
||||||
|
RadixTreeKeys int64
|
||||||
|
RadixTreeNodes int64
|
||||||
|
Groups int64
|
||||||
|
LastGeneratedID string
|
||||||
|
FirstEntry XMessage
|
||||||
|
LastEntry XMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*XInfoStreamCmd)(nil)
|
||||||
|
|
||||||
|
func NewXInfoStreamCmd(ctx context.Context, stream string) *XInfoStreamCmd {
|
||||||
|
return &XInfoStreamCmd{
|
||||||
|
baseCmd: baseCmd{
|
||||||
|
ctx: ctx,
|
||||||
|
args: []interface{}{"xinfo", "stream", stream},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *XInfoStreamCmd) Val() *XInfoStream {
|
||||||
|
return cmd.val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *XInfoStreamCmd) Result() (*XInfoStream, error) {
|
||||||
|
return cmd.val, cmd.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *XInfoStreamCmd) String() string {
|
||||||
|
return cmdString(cmd, cmd.val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *XInfoStreamCmd) readReply(rd *proto.Reader) error {
|
||||||
|
v, err := rd.ReadReply(xStreamInfoParser)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.val = v.(*XInfoStream)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func xStreamInfoParser(rd *proto.Reader, n int64) (interface{}, error) {
|
||||||
|
if n != 14 {
|
||||||
|
return nil, fmt.Errorf("redis: got %d elements in XINFO STREAM reply,"+
|
||||||
|
"wanted 14", n)
|
||||||
|
}
|
||||||
|
var info XInfoStream
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
key, err := rd.ReadString()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch key {
|
||||||
|
case "length":
|
||||||
|
info.Length, err = rd.ReadIntReply()
|
||||||
|
case "radix-tree-keys":
|
||||||
|
info.RadixTreeKeys, err = rd.ReadIntReply()
|
||||||
|
case "radix-tree-nodes":
|
||||||
|
info.RadixTreeNodes, err = rd.ReadIntReply()
|
||||||
|
case "groups":
|
||||||
|
info.Groups, err = rd.ReadIntReply()
|
||||||
|
case "last-generated-id":
|
||||||
|
info.LastGeneratedID, err = rd.ReadString()
|
||||||
|
case "first-entry":
|
||||||
|
info.FirstEntry, err = readXMessage(rd)
|
||||||
|
case "last-entry":
|
||||||
|
info.LastEntry, err = readXMessage(rd)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("redis: unexpected content %s "+
|
||||||
|
"in XINFO STREAM reply", key)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
type ZSliceCmd struct {
|
type ZSliceCmd struct {
|
||||||
baseCmd
|
baseCmd
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,7 @@ type Cmdable interface {
|
||||||
XTrim(ctx context.Context, key string, maxLen int64) *IntCmd
|
XTrim(ctx context.Context, key string, maxLen int64) *IntCmd
|
||||||
XTrimApprox(ctx context.Context, key string, maxLen int64) *IntCmd
|
XTrimApprox(ctx context.Context, key string, maxLen int64) *IntCmd
|
||||||
XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd
|
XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd
|
||||||
|
XInfoStream(ctx context.Context, key string) *XInfoStreamCmd
|
||||||
|
|
||||||
BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
|
BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
|
||||||
BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
|
BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
|
||||||
|
@ -1699,6 +1700,12 @@ func (c cmdable) XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c cmdable) XInfoStream(ctx context.Context, key string) *XInfoStreamCmd {
|
||||||
|
cmd := NewXInfoStreamCmd(ctx, key)
|
||||||
|
_ = c(ctx, cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Z represents sorted set member.
|
// Z represents sorted set member.
|
||||||
|
|
Loading…
Reference in New Issue