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.
78 lines
2.3 KiB
Go
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()
|
|
}
|