1
0
mirror of https://github.com/redis/go-redis.git synced 2025-07-29 17:41:15 +03:00

Fix multi/exec and add more commands.

This commit is contained in:
Vladimir Mihailenco
2012-07-26 18:16:17 +03:00
parent a74d9a5801
commit 153bd05fb7
4 changed files with 1653 additions and 199 deletions

View File

@ -1,6 +1,7 @@
package redis
import (
"fmt"
"io"
"sync"
@ -16,6 +17,8 @@ type Client struct {
disconnect disconnectFunc
currConn io.ReadWriter
rd *bufreader.Reader
reqs []Req
}
func NewClient(connect connectFunc, disconnect disconnectFunc) *Client {
@ -26,6 +29,16 @@ func NewClient(connect connectFunc, disconnect disconnectFunc) *Client {
}
}
func NewMultiClient(connect connectFunc, disconnect disconnectFunc) *Client {
return &Client{
rd: bufreader.NewSizedReader(8192),
connect: connect,
disconnect: disconnect,
reqs: make([]Req, 0),
}
}
func (c *Client) Close() error {
if c.disconnect != nil {
c.disconnect(c.currConn)
@ -71,6 +84,8 @@ func (c *Client) ReadReply() (*bufreader.Reader, error) {
}
func (c *Client) WriteRead(buf []byte) (*bufreader.Reader, error) {
c.mtx.Lock()
defer c.mtx.Unlock()
if err := c.WriteReq(buf); err != nil {
return nil, err
}
@ -78,16 +93,84 @@ func (c *Client) WriteRead(buf []byte) (*bufreader.Reader, error) {
}
func (c *Client) Run(req Req) {
c.mtx.Lock()
c.run(req)
c.mtx.Unlock()
}
if c.reqs != nil {
c.mtx.Lock()
c.reqs = append(c.reqs, req)
c.mtx.Unlock()
return
}
func (c *Client) run(req Req) {
buf, err := c.WriteRead(req.Req())
rd, err := c.WriteRead(req.Req())
if err != nil {
req.SetErr(err)
return
}
req.ParseReply(buf)
req.ParseReply(rd)
}
//------------------------------------------------------------------------------
func (c *Client) Discard() {
if c.reqs == nil {
panic("MultiClient required")
}
c.mtx.Lock()
c.reqs = c.reqs[:0]
c.mtx.Unlock()
}
func (c *Client) Exec() ([]Req, error) {
if c.reqs == nil {
panic("MultiClient required")
}
c.mtx.Lock()
reqs := c.reqs
c.reqs = make([]Req, 0)
c.mtx.Unlock()
multiReq := make([]byte, 0, 1024)
multiReq = append(multiReq, PackReq([]string{"MULTI"})...)
for _, req := range reqs {
multiReq = append(multiReq, req.Req()...)
}
multiReq = append(multiReq, PackReq([]string{"EXEC"})...)
rd, err := c.WriteRead(multiReq)
if err != nil {
return nil, err
}
statusReq := NewStatusReq()
// multi
statusReq.ParseReply(rd)
_, err = statusReq.Reply()
if err != nil {
return nil, err
}
for _ = range reqs {
// queue
statusReq.ParseReply(rd)
_, err = statusReq.Reply()
if err != nil {
return nil, err
}
}
line, err := rd.ReadLine('\n')
if err != nil {
return nil, err
}
if line[0] != '*' {
return nil, fmt.Errorf("Expected '*', but got line %q of %q.", line, rd.Bytes())
}
for _, req := range reqs {
req.ParseReply(rd)
}
return reqs, nil
}