Files
remark42/backend/vendor/github.com/go-pkgz/lcw/eventbus/redis.go
T
Dmitry Verkhoturov 9ad3be2e97 bump go modules, make auth dev hostname customisable
After this commit, dev auth would start working with the `REMARK_URL`
hostname instead of the previously hardcoded 127.0.0.1.

Breaks development setup where `REMARK_URL` was set
to a non-standard value and dev auth was running on 127.0.0.1
and working, as, after that change, it would stop working.
2022-08-26 23:35:57 +02:00

78 lines
2.3 KiB
Go

package eventbus
import (
"context"
"fmt"
"strings"
"time"
"github.com/go-redis/redis/v8"
"github.com/hashicorp/go-multierror"
)
// NewRedisPubSub creates new RedisPubSub with given parameters.
// Returns an error in case of problems with creating PubSub client for specified channel.
func NewRedisPubSub(addr, channel string) (*RedisPubSub, error) {
client := redis.NewClient(&redis.Options{Addr: addr})
pubSub := client.Subscribe(context.Background(), channel)
// wait for subscription to be created and ignore the message
if _, err := pubSub.Receive(context.Background()); err != nil {
_ = client.Close()
return nil, fmt.Errorf("problem subscribing to channel %s on address %s: %w", channel, addr, err)
}
return &RedisPubSub{client: client, pubSub: pubSub, channel: channel, done: make(chan struct{})}, nil
}
// RedisPubSub provides Redis implementation for PubSub interface
type RedisPubSub struct {
client *redis.Client
pubSub *redis.PubSub
channel string
done chan struct{}
}
// Subscribe calls provided function on subscription channel provided on new RedisPubSub instance creation.
// Should not be called more than once. Spawns a goroutine and does not return an error.
func (m *RedisPubSub) Subscribe(fn func(fromID, key string)) error {
go func(done <-chan struct{}, pubsub *redis.PubSub) {
for {
select {
case <-done:
return
default:
}
msg, err := pubsub.ReceiveTimeout(context.Background(), time.Second*10)
if err != nil {
continue
}
// Process the message
if msg, ok := msg.(*redis.Message); ok {
payload := strings.Split(msg.Payload, "$")
fn(payload[0], strings.Join(payload[1:], "$"))
}
}
}(m.done, m.pubSub)
return nil
}
// Publish publishes provided message to channel provided on new RedisPubSub instance creation
func (m *RedisPubSub) Publish(fromID, key string) error {
return m.client.Publish(context.Background(), m.channel, fromID+"$"+key).Err()
}
// Close cleans up running goroutines and closes Redis clients
func (m *RedisPubSub) Close() error {
close(m.done)
errs := new(multierror.Error)
if err := m.pubSub.Close(); err != nil {
errs = multierror.Append(errs, fmt.Errorf("problem closing pubSub client: %w", err))
}
if err := m.client.Close(); err != nil {
errs = multierror.Append(errs, fmt.Errorf("problem closing redis client: %w", err))
}
return errs.ErrorOrNil()
}