mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-22 17:31:03 +01:00
99 lines
2.1 KiB
Go
99 lines
2.1 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"crawlab/utils"
|
|
"fmt"
|
|
"github.com/apex/log"
|
|
"github.com/gomodule/redigo/redis"
|
|
errors2 "github.com/pkg/errors"
|
|
"time"
|
|
)
|
|
|
|
type ConsumeFunc func(message redis.Message) error
|
|
|
|
func (r *Redis) Close() {
|
|
err := r.pool.Close()
|
|
if err != nil {
|
|
log.Errorf("redis close error.")
|
|
}
|
|
}
|
|
func (r *Redis) subscribe(ctx context.Context, consume ConsumeFunc, channel ...string) error {
|
|
psc := redis.PubSubConn{Conn: r.pool.Get()}
|
|
if err := psc.Subscribe(redis.Args{}.AddFlat(channel)...); err != nil {
|
|
return err
|
|
}
|
|
done := make(chan error, 1)
|
|
tick := time.NewTicker(time.Second * 3)
|
|
defer tick.Stop()
|
|
go func() {
|
|
defer utils.Close(psc)
|
|
for {
|
|
switch msg := psc.Receive().(type) {
|
|
case error:
|
|
done <- fmt.Errorf("redis pubsub receive err: %v", msg)
|
|
return
|
|
case redis.Message:
|
|
if err := consume(msg); err != nil {
|
|
fmt.Printf("redis pubsub consume message err: %v", err)
|
|
continue
|
|
}
|
|
case redis.Subscription:
|
|
fmt.Println(msg)
|
|
|
|
if msg.Count == 0 {
|
|
// all channels are unsubscribed
|
|
return
|
|
}
|
|
}
|
|
|
|
}
|
|
}()
|
|
// start a new goroutine to receive message
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
if err := psc.Unsubscribe(); err != nil {
|
|
fmt.Printf("redis pubsub unsubscribe err: %v \n", err)
|
|
}
|
|
done <- nil
|
|
case <-tick.C:
|
|
if err := psc.Ping(""); err != nil {
|
|
fmt.Printf("ping message error: %s \n", err)
|
|
//done <- err
|
|
}
|
|
case err := <-done:
|
|
close(done)
|
|
return err
|
|
}
|
|
}
|
|
|
|
}
|
|
func (r *Redis) Subscribe(ctx context.Context, consume ConsumeFunc, channel ...string) error {
|
|
index := 0
|
|
go func() {
|
|
for {
|
|
err := r.subscribe(ctx, consume, channel...)
|
|
fmt.Println(err)
|
|
|
|
if err == nil {
|
|
index = 0
|
|
break
|
|
}
|
|
time.Sleep(5 * time.Second)
|
|
index += 1
|
|
fmt.Printf("try reconnect %d times \n", index)
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
func (r *Redis) Publish(channel, message string) (n int, err error) {
|
|
conn := r.pool.Get()
|
|
defer utils.Close(conn)
|
|
n, err = redis.Int(conn.Do("PUBLISH", channel, message))
|
|
if err != nil {
|
|
return 0, errors2.Wrapf(err, "redis publish %s %s", channel, message)
|
|
}
|
|
return
|
|
}
|