Skip to content

Instantly share code, notes, and snippets.

@miguelmota
Created October 6, 2018 21:12
Show Gist options
  • Save miguelmota/ca4a7a66d8a7b014fad09d17df4b6e18 to your computer and use it in GitHub Desktop.
Save miguelmota/ca4a7a66d8a7b014fad09d17df4b6e18 to your computer and use it in GitHub Desktop.
Golang redis pub/sub example
package pubsub
import (
"github.com/garyburd/redigo/redis"
log "github.com/sirupsen/logrus"
)
// Service service
type Service struct {
pool *redis.Pool
conn redis.Conn
}
// NewInput input for constructor
type NewInput struct {
RedisURL string
}
// New return new service
func New(input *NewInput) *Service {
if input == nil {
log.Fatal("input is required")
}
var redispool *redis.Pool
redispool = &redis.Pool{
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", input.RedisURL)
},
}
// Get a connection
conn := redispool.Get()
defer conn.Close()
// Test the connection
_, err := conn.Do("PING")
if err != nil {
log.Fatalf("can't connect to the redis database, got error:\n%v", err)
}
return &Service{
pool: redispool,
conn: conn,
}
}
// Publish publish key value
func (s *Service) Publish(key string, value string) error {
conn := s.pool.Get()
conn.Do("PUBLISH", key, value)
return nil
}
// Subscribe subscribe
func (s *Service) Subscribe(key string, msg chan []byte) error {
rc := s.pool.Get()
psc := redis.PubSubConn{Conn: rc}
if err := psc.PSubscribe(key); err != nil {
return err
}
go func() {
for {
switch v := psc.Receive().(type) {
case redis.PMessage:
msg <- v.Data
}
}
}()
return nil
}
package pubsub
import (
"fmt"
"log"
"os"
"testing"
"time"
)
func TestPublish(t *testing.T) {
t.Parallel()
svc := New(&NewInput{
RedisURL: os.Getenv("REDIS_URL"),
})
err := svc.Publish("test/foo", "bar")
if err != nil {
log.Fatal(err)
}
}
func TestSubscribe(t *testing.T) {
t.Parallel()
svc := New(&NewInput{
RedisURL: os.Getenv("REDIS_URL"),
})
channel := fmt.Sprintf("test/%s", time.Now().Add(10*time.Second).String())
val := time.Now().String()
reply := make(chan []byte)
err := svc.Subscribe(channel, reply)
if err != nil {
log.Fatal(err)
}
err = svc.Publish(channel, val)
if err != nil {
log.Fatal(err)
}
t.Run("message", func(t *testing.T) {
msg := <-reply
if string(msg) != val {
t.Fatal("expected correct reply message")
}
log.Printf("recieved %q", string(msg))
})
}
@hongnguyenhuu96
Copy link

how do you unsubscribe a channel?

@gargakshit
Copy link

how do you unsubscribe a channel?

I guess you can close the connection (not the pool) as it makes a new connection for each subscription

@isqad
Copy link

isqad commented Apr 14, 2021

There is unsubscribe redis command
https://redis.io/commands/unsubscribe

@synaptic-cleft
Copy link

I assume hongnguyenhuu96 meant how to unsubscribe using this library.

According to the documentation (here https://pkg.go.dev/github.com/gomodule/redigo/redis#PubSubConn.PUnsubscribe ) you'd call the PUnsubscribe() method on PubSubConn with the according channel. So in this example it would be:

psc.PUnsubscribe(key)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment