@@ -14,7 +14,10 @@ import (
1414 log "github.com/sirupsen/logrus"
1515)
1616
17- const redisUsageChannel = "usage"
17+ const (
18+ redisUsageChannel = "usage"
19+ redisErrorsChannel = "errors"
20+ )
1821
1922type redisSubscriptionCommand struct {
2023 args []string
@@ -150,15 +153,15 @@ func (s *Server) handleRedisConnection(conn net.Conn, reader *bufio.Reader) {
150153 }
151154 continue
152155 }
153- if ! strings .EqualFold (channel , redisUsageChannel ) {
156+ messages , unsubscribe , ok := subscribeRedisChannel (channel )
157+ if ! ok {
154158 _ = writeRedisError (writer , fmt .Sprintf ("ERR unsupported channel '%s'" , channel ))
155159 if ! flush () {
156160 return
157161 }
158162 continue
159163 }
160- messages , unsubscribe := redisqueue .SubscribeUsage ()
161- if errWrite := writeRedisPubSubSubscribe (writer , redisUsageChannel , 1 ); errWrite != nil {
164+ if errWrite := writeRedisPubSubSubscribe (writer , channel , 1 ); errWrite != nil {
162165 unsubscribe ()
163166 log .Errorf ("redis protocol subscribe response error: %v" , errWrite )
164167 return
@@ -167,7 +170,7 @@ func (s *Server) handleRedisConnection(conn net.Conn, reader *bufio.Reader) {
167170 unsubscribe ()
168171 return
169172 }
170- s .streamRedisUsageSubscription (reader , writer , messages , unsubscribe )
173+ s .streamRedisSubscription (reader , writer , channel , messages , unsubscribe )
171174 return
172175 case "LPOP" , "RPOP" :
173176 count , hasCount , ok := parsePopCount (args )
@@ -185,7 +188,14 @@ func (s *Server) handleRedisConnection(conn net.Conn, reader *bufio.Reader) {
185188 }
186189 continue
187190 }
188- items := redisqueue .PopOldest (count )
191+ items , ok := popRedisQueueItems (args [1 ], count )
192+ if ! ok {
193+ _ = writeRedisError (writer , fmt .Sprintf ("ERR unsupported channel '%s'" , strings .TrimSpace (args [1 ])))
194+ if ! flush () {
195+ return
196+ }
197+ continue
198+ }
189199 if hasCount {
190200 _ = writeRedisArrayOfBulkStrings (writer , items )
191201 if ! flush () {
@@ -213,7 +223,29 @@ func (s *Server) handleRedisConnection(conn net.Conn, reader *bufio.Reader) {
213223 }
214224}
215225
216- func (s * Server ) streamRedisUsageSubscription (reader * bufio.Reader , writer * bufio.Writer , messages <- chan []byte , unsubscribe func ()) {
226+ func subscribeRedisChannel (channel string ) (<- chan []byte , func (), bool ) {
227+ switch strings .ToLower (strings .TrimSpace (channel )) {
228+ case redisUsageChannel :
229+ messages , unsubscribe := redisqueue .SubscribeUsage ()
230+ return messages , unsubscribe , true
231+ case redisErrorsChannel :
232+ messages , unsubscribe := redisqueue .SubscribeErrors ()
233+ return messages , unsubscribe , true
234+ default :
235+ return nil , nil , false
236+ }
237+ }
238+
239+ func popRedisQueueItems (channel string , count int ) ([][]byte , bool ) {
240+ switch strings .ToLower (strings .TrimSpace (channel )) {
241+ case redisUsageChannel :
242+ return redisqueue .PopOldest (count ), true
243+ default :
244+ return nil , false
245+ }
246+ }
247+
248+ func (s * Server ) streamRedisSubscription (reader * bufio.Reader , writer * bufio.Writer , channel string , messages <- chan []byte , unsubscribe func ()) {
217249 if unsubscribe == nil {
218250 return
219251 }
@@ -231,7 +263,7 @@ func (s *Server) streamRedisUsageSubscription(reader *bufio.Reader, writer *bufi
231263 if ! ok {
232264 return
233265 }
234- if errWrite := writeRedisPubSubMessage (writer , redisUsageChannel , msg ); errWrite != nil {
266+ if errWrite := writeRedisPubSubMessage (writer , channel , msg ); errWrite != nil {
235267 log .Errorf ("redis protocol publish message error: %v" , errWrite )
236268 return
237269 }
@@ -243,7 +275,7 @@ func (s *Server) streamRedisUsageSubscription(reader *bufio.Reader, writer *bufi
243275 if ! ok {
244276 return
245277 }
246- keepOpen := handleRedisSubscriptionCommand (writer , command )
278+ keepOpen := handleRedisSubscriptionCommand (writer , channel , command )
247279 if errFlush := writer .Flush (); errFlush != nil {
248280 log .Errorf ("redis protocol flush error: %v" , errFlush )
249281 return
@@ -277,7 +309,7 @@ func readRedisSubscriptionCommands(reader *bufio.Reader, commands chan<- redisSu
277309 }
278310}
279311
280- func handleRedisSubscriptionCommand (writer * bufio.Writer , command redisSubscriptionCommand ) bool {
312+ func handleRedisSubscriptionCommand (writer * bufio.Writer , channel string , command redisSubscriptionCommand ) bool {
281313 if command .err != nil {
282314 _ = writeRedisError (writer , "ERR " + command .err .Error ())
283315 return false
@@ -297,7 +329,7 @@ func handleRedisSubscriptionCommand(writer *bufio.Writer, command redisSubscript
297329 _ = writeRedisPubSubPong (writer , payload )
298330 return true
299331 case "UNSUBSCRIBE" :
300- _ = writeRedisPubSubUnsubscribe (writer , redisUsageChannel , 0 )
332+ _ = writeRedisPubSubUnsubscribe (writer , channel , 0 )
301333 return false
302334 case "QUIT" :
303335 _ = writeRedisSimpleString (writer , "OK" )
0 commit comments