Skip to content

Commit ee3ea5c

Browse files
authored
Merge pull request #158 from alicebob/seterror
introduce SetError()
2 parents cca8a28 + a204470 commit ee3ea5c

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

cmd_connection_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,24 @@ func TestQuit(t *testing.T) {
170170
assert(t, err != nil, "QUIT closed the client")
171171
equals(t, "", v)
172172
}
173+
174+
func TestSetError(t *testing.T) {
175+
s, err := Run()
176+
ok(t, err)
177+
defer s.Close()
178+
c, err := redis.Dial("tcp", s.Addr())
179+
ok(t, err)
180+
181+
r, err := redis.String(c.Do("PING"))
182+
ok(t, err)
183+
equals(t, "PONG", r)
184+
185+
s.SetError("LOADING Redis is loading the dataset in memory")
186+
_, err = c.Do("PING", "hi")
187+
mustFail(t, err, "LOADING Redis is loading the dataset in memory")
188+
189+
s.SetError("")
190+
r, err = redis.String(c.Do("PING"))
191+
ok(t, err)
192+
equals(t, "PONG", r)
193+
}

miniredis.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,21 @@ func (m *Miniredis) SetTime(t time.Time) {
354354
m.now = t
355355
}
356356

357+
// make every command return this message. For example:
358+
// LOADING Redis is loading the dataset in memory
359+
// MASTERDOWN Link with MASTER is down and replica-serve-stale-data is set to 'no'.
360+
// Clear it with an empty string. Don't add newlines.
361+
func (m *Miniredis) SetError(msg string) {
362+
cb := server.Hook(nil)
363+
if msg != "" {
364+
cb = func(c *server.Peer, cmd string, args ...string) bool {
365+
c.WriteError(msg)
366+
return true
367+
}
368+
}
369+
m.srv.SetPreHook(cb)
370+
}
371+
357372
// handleAuth returns false if connection has no access. It sends the reply.
358373
func (m *Miniredis) handleAuth(c *server.Peer) bool {
359374
if getCtx(c).nested {

server/server.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@ type Cmd func(c *Peer, cmd string, args []string)
2525

2626
type DisconnectHandler func(c *Peer)
2727

28+
// Hook is can be added to run before every cmd. Return true if the command is done.
29+
type Hook func(*Peer, string, ...string) bool
30+
2831
// Server is a simple redis server
2932
type Server struct {
3033
l net.Listener
3134
cmds map[string]Cmd
35+
preHook Hook
3236
peers map[net.Conn]struct{}
3337
mu sync.Mutex
3438
wg sync.WaitGroup
@@ -63,6 +67,13 @@ func NewServer(addr string) (*Server, error) {
6367
return &s, nil
6468
}
6569

70+
// (un)set a hook which is ran before every call. It returns true if the command is done.
71+
func (s *Server) SetPreHook(h Hook) {
72+
s.mu.Lock()
73+
s.preHook = h
74+
s.mu.Unlock()
75+
}
76+
6677
func (s *Server) serve(l net.Listener) {
6778
for {
6879
conn, err := l.Accept()
@@ -160,6 +171,15 @@ func (s *Server) servePeer(c net.Conn) {
160171
func (s *Server) Dispatch(c *Peer, args []string) {
161172
cmd, args := args[0], args[1:]
162173
cmdUp := strings.ToUpper(cmd)
174+
s.mu.Lock()
175+
h := s.preHook
176+
s.mu.Unlock()
177+
if h != nil {
178+
if h(c, cmdUp, args...) {
179+
return
180+
}
181+
}
182+
163183
s.mu.Lock()
164184
cb, ok := s.cmds[cmdUp]
165185
s.mu.Unlock()

0 commit comments

Comments
 (0)