mirror of
https://github.com/hibiken/asynq.git
synced 2024-12-27 16:13:40 +08:00
Merge remote-tracking branch 'jerbob92-fork/feature/implement-reusing-redis-client' into develop
This commit is contained in:
commit
5daa3c52ed
20
client.go
20
client.go
@ -10,11 +10,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/hibiken/asynq/internal/base"
|
"github.com/hibiken/asynq/internal/base"
|
||||||
"github.com/hibiken/asynq/internal/errors"
|
"github.com/hibiken/asynq/internal/errors"
|
||||||
"github.com/hibiken/asynq/internal/rdb"
|
"github.com/hibiken/asynq/internal/rdb"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Client is responsible for scheduling tasks.
|
// A Client is responsible for scheduling tasks.
|
||||||
@ -25,15 +25,26 @@ import (
|
|||||||
// Clients are safe for concurrent use by multiple goroutines.
|
// Clients are safe for concurrent use by multiple goroutines.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
broker base.Broker
|
broker base.Broker
|
||||||
|
// When a Client has been created with an existing Redis connection, we do
|
||||||
|
// not want to close it.
|
||||||
|
sharedConnection bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a new Client instance given a redis connection option.
|
// NewClient returns a new Client instance given a redis connection option.
|
||||||
func NewClient(r RedisConnOpt) *Client {
|
func NewClient(r RedisConnOpt) *Client {
|
||||||
c, ok := r.MakeRedisClient().(redis.UniversalClient)
|
redisClient, ok := r.MakeRedisClient().(redis.UniversalClient)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("asynq: unsupported RedisConnOpt type %T", r))
|
panic(fmt.Sprintf("asynq: unsupported RedisConnOpt type %T", r))
|
||||||
}
|
}
|
||||||
return &Client{broker: rdb.NewRDB(c)}
|
client := NewClientFromRedisClient(redisClient)
|
||||||
|
client.sharedConnection = false
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClientFromRedisClient returns a new Client instance given a redis client.
|
||||||
|
// Warning: the redis client will not be closed by Asynq, you are responsible for closing.
|
||||||
|
func NewClientFromRedisClient(c redis.UniversalClient) *Client {
|
||||||
|
return &Client{broker: rdb.NewRDB(c), sharedConnection: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
type OptionType int
|
type OptionType int
|
||||||
@ -307,6 +318,9 @@ var (
|
|||||||
|
|
||||||
// Close closes the connection with redis.
|
// Close closes the connection with redis.
|
||||||
func (c *Client) Close() error {
|
func (c *Client) Close() error {
|
||||||
|
if c.sharedConnection {
|
||||||
|
return fmt.Errorf("redis connection is shared so the Client can't be closed through asynq")
|
||||||
|
}
|
||||||
return c.broker.Close()
|
return c.broker.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"github.com/hibiken/asynq/internal/base"
|
"github.com/hibiken/asynq/internal/base"
|
||||||
h "github.com/hibiken/asynq/internal/testutil"
|
h "github.com/hibiken/asynq/internal/testutil"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestClientEnqueueWithProcessAtOption(t *testing.T) {
|
func TestClientEnqueueWithProcessAtOption(t *testing.T) {
|
||||||
@ -143,11 +144,7 @@ func TestClientEnqueueWithProcessAtOption(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientEnqueue(t *testing.T) {
|
func testClientEnqueue(t *testing.T, client *Client, r redis.UniversalClient) {
|
||||||
r := setup(t)
|
|
||||||
client := NewClient(getRedisConnOpt(t))
|
|
||||||
defer client.Close()
|
|
||||||
|
|
||||||
task := NewTask("send_email", h.JSON(map[string]interface{}{"to": "customer@gmail.com", "from": "merchant@example.com"}))
|
task := NewTask("send_email", h.JSON(map[string]interface{}{"to": "customer@gmail.com", "from": "merchant@example.com"}))
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
@ -478,6 +475,24 @@ func TestClientEnqueue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClientEnqueue(t *testing.T) {
|
||||||
|
r := setup(t)
|
||||||
|
client := NewClient(getRedisConnOpt(t))
|
||||||
|
defer client.Close()
|
||||||
|
testClientEnqueue(t, client, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientFromRedisClientEnqueue(t *testing.T) {
|
||||||
|
r := setup(t)
|
||||||
|
redisClient := getRedisConnOpt(t).MakeRedisClient().(redis.UniversalClient)
|
||||||
|
client := NewClientFromRedisClient(redisClient)
|
||||||
|
testClientEnqueue(t, client, r)
|
||||||
|
err := client.Close()
|
||||||
|
if err == nil {
|
||||||
|
t.Error("client.Close() should have failed because of a shared client but it didn't")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestClientEnqueueWithGroupOption(t *testing.T) {
|
func TestClientEnqueueWithGroupOption(t *testing.T) {
|
||||||
r := setup(t)
|
r := setup(t)
|
||||||
client := NewClient(getRedisConnOpt(t))
|
client := NewClient(getRedisConnOpt(t))
|
||||||
|
17
inspector.go
17
inspector.go
@ -10,16 +10,19 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
|
||||||
"github.com/hibiken/asynq/internal/base"
|
"github.com/hibiken/asynq/internal/base"
|
||||||
"github.com/hibiken/asynq/internal/errors"
|
"github.com/hibiken/asynq/internal/errors"
|
||||||
"github.com/hibiken/asynq/internal/rdb"
|
"github.com/hibiken/asynq/internal/rdb"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Inspector is a client interface to inspect and mutate the state of
|
// Inspector is a client interface to inspect and mutate the state of
|
||||||
// queues and tasks.
|
// queues and tasks.
|
||||||
type Inspector struct {
|
type Inspector struct {
|
||||||
rdb *rdb.RDB
|
rdb *rdb.RDB
|
||||||
|
// When an Inspector has been created with an existing Redis connection, we do
|
||||||
|
// not want to close it.
|
||||||
|
sharedConnection bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new instance of Inspector.
|
// New returns a new instance of Inspector.
|
||||||
@ -28,13 +31,25 @@ func NewInspector(r RedisConnOpt) *Inspector {
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("inspeq: unsupported RedisConnOpt type %T", r))
|
panic(fmt.Sprintf("inspeq: unsupported RedisConnOpt type %T", r))
|
||||||
}
|
}
|
||||||
|
inspector := NewInspectorFromRedisClient(c)
|
||||||
|
inspector.sharedConnection = false
|
||||||
|
return inspector
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFromRedisClient returns a new instance of Inspector.
|
||||||
|
// Warning: the redis client will not be closed by Asynq, you are responsible for closing.
|
||||||
|
func NewInspectorFromRedisClient(c redis.UniversalClient) *Inspector {
|
||||||
return &Inspector{
|
return &Inspector{
|
||||||
rdb: rdb.NewRDB(c),
|
rdb: rdb.NewRDB(c),
|
||||||
|
sharedConnection: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the connection with redis.
|
// Close closes the connection with redis.
|
||||||
func (i *Inspector) Close() error {
|
func (i *Inspector) Close() error {
|
||||||
|
if i.sharedConnection {
|
||||||
|
return fmt.Errorf("redis connection is shared so the Inspector can't be closed through asynq")
|
||||||
|
}
|
||||||
return i.rdb.Close()
|
return i.rdb.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +22,7 @@ import (
|
|||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInspectorQueues(t *testing.T) {
|
func testInspectorQueues(t *testing.T, inspector *Inspector, r redis.UniversalClient) {
|
||||||
r := setup(t)
|
|
||||||
defer r.Close()
|
|
||||||
inspector := NewInspector(getRedisConnOpt(t))
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
queues []string
|
queues []string
|
||||||
}{
|
}{
|
||||||
@ -52,7 +48,21 @@ func TestInspectorQueues(t *testing.T) {
|
|||||||
t.Errorf("Queues() = %v, want %v; (-want, +got)\n%s", got, tc.queues, diff)
|
t.Errorf("Queues() = %v, want %v; (-want, +got)\n%s", got, tc.queues, diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInspectorQueues(t *testing.T) {
|
||||||
|
r := setup(t)
|
||||||
|
defer r.Close()
|
||||||
|
inspector := NewInspector(getRedisConnOpt(t))
|
||||||
|
testInspectorQueues(t, inspector, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInspectorFromRedisClientQueues(t *testing.T) {
|
||||||
|
r := setup(t)
|
||||||
|
defer r.Close()
|
||||||
|
redisClient := getRedisConnOpt(t).MakeRedisClient().(redis.UniversalClient)
|
||||||
|
inspector := NewInspectorFromRedisClient(redisClient)
|
||||||
|
testInspectorQueues(t, inspector, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInspectorDeleteQueue(t *testing.T) {
|
func TestInspectorDeleteQueue(t *testing.T) {
|
||||||
|
20
scheduler.go
20
scheduler.go
@ -10,11 +10,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/hibiken/asynq/internal/base"
|
"github.com/hibiken/asynq/internal/base"
|
||||||
"github.com/hibiken/asynq/internal/log"
|
"github.com/hibiken/asynq/internal/log"
|
||||||
"github.com/hibiken/asynq/internal/rdb"
|
"github.com/hibiken/asynq/internal/rdb"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,15 +43,27 @@ type Scheduler struct {
|
|||||||
// to avoid using cron.EntryID as the public API of
|
// to avoid using cron.EntryID as the public API of
|
||||||
// the Scheduler.
|
// the Scheduler.
|
||||||
idmap map[string]cron.EntryID
|
idmap map[string]cron.EntryID
|
||||||
|
// When a Scheduler has been created with an existing Redis connection, we do
|
||||||
|
// not want to close it.
|
||||||
|
sharedConnection bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewScheduler returns a new Scheduler instance given the redis connection option.
|
// NewScheduler returns a new Scheduler instance given the redis connection option.
|
||||||
// The parameter opts is optional, defaults will be used if opts is set to nil
|
// The parameter opts is optional, defaults will be used if opts is set to nil
|
||||||
func NewScheduler(r RedisConnOpt, opts *SchedulerOpts) *Scheduler {
|
func NewScheduler(r RedisConnOpt, opts *SchedulerOpts) *Scheduler {
|
||||||
c, ok := r.MakeRedisClient().(redis.UniversalClient)
|
redisClient, ok := r.MakeRedisClient().(redis.UniversalClient)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("asynq: unsupported RedisConnOpt type %T", r))
|
panic(fmt.Sprintf("asynq: unsupported RedisConnOpt type %T", r))
|
||||||
}
|
}
|
||||||
|
scheduler := NewSchedulerFromRedisClient(redisClient, opts)
|
||||||
|
scheduler.sharedConnection = false
|
||||||
|
return scheduler
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSchedulerFromRedisClient returns a new Scheduler instance given a redis client.
|
||||||
|
// The parameter opts is optional, defaults will be used if opts is set to nil.
|
||||||
|
// Warning: the redis client will not be closed by Asynq, you are responsible for closing.
|
||||||
|
func NewSchedulerFromRedisClient(c redis.UniversalClient, opts *SchedulerOpts) *Scheduler {
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
opts = &SchedulerOpts{}
|
opts = &SchedulerOpts{}
|
||||||
}
|
}
|
||||||
@ -72,7 +84,7 @@ func NewScheduler(r RedisConnOpt, opts *SchedulerOpts) *Scheduler {
|
|||||||
id: generateSchedulerID(),
|
id: generateSchedulerID(),
|
||||||
state: &serverState{value: srvStateNew},
|
state: &serverState{value: srvStateNew},
|
||||||
logger: logger,
|
logger: logger,
|
||||||
client: NewClient(r),
|
client: NewClientFromRedisClient(c),
|
||||||
rdb: rdb.NewRDB(c),
|
rdb: rdb.NewRDB(c),
|
||||||
cron: cron.New(cron.WithLocation(loc)),
|
cron: cron.New(cron.WithLocation(loc)),
|
||||||
location: loc,
|
location: loc,
|
||||||
@ -262,7 +274,9 @@ func (s *Scheduler) Shutdown() {
|
|||||||
|
|
||||||
s.clearHistory()
|
s.clearHistory()
|
||||||
s.client.Close()
|
s.client.Close()
|
||||||
|
if !s.sharedConnection {
|
||||||
s.rdb.Close()
|
s.rdb.Close()
|
||||||
|
}
|
||||||
s.logger.Info("Scheduler stopped")
|
s.logger.Info("Scheduler stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package asynq
|
package asynq
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -58,6 +59,7 @@ func TestSchedulerRegister(t *testing.T) {
|
|||||||
|
|
||||||
r := setup(t)
|
r := setup(t)
|
||||||
|
|
||||||
|
// Tests for new redis connection.
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
scheduler := NewScheduler(getRedisConnOpt(t), nil)
|
scheduler := NewScheduler(getRedisConnOpt(t), nil)
|
||||||
if _, err := scheduler.Register(tc.cronspec, tc.task, tc.opts...); err != nil {
|
if _, err := scheduler.Register(tc.cronspec, tc.task, tc.opts...); err != nil {
|
||||||
@ -75,6 +77,28 @@ func TestSchedulerRegister(t *testing.T) {
|
|||||||
t.Errorf("mismatch found in queue %q: (-want,+got)\n%s", tc.queue, diff)
|
t.Errorf("mismatch found in queue %q: (-want,+got)\n%s", tc.queue, diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = setup(t)
|
||||||
|
|
||||||
|
// Tests for existing redis connection.
|
||||||
|
for _, tc := range tests {
|
||||||
|
redisClient := getRedisConnOpt(t).MakeRedisClient().(redis.UniversalClient)
|
||||||
|
scheduler := NewSchedulerFromRedisClient(redisClient, nil)
|
||||||
|
if _, err := scheduler.Register(tc.cronspec, tc.task, tc.opts...); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scheduler.Start(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
time.Sleep(tc.wait)
|
||||||
|
scheduler.Shutdown()
|
||||||
|
|
||||||
|
got := testutil.GetPendingMessages(t, r, tc.queue)
|
||||||
|
if diff := cmp.Diff(tc.want, got, testutil.IgnoreIDOpt); diff != "" {
|
||||||
|
t.Errorf("mismatch found in queue %q: (-want,+got)\n%s", tc.queue, diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSchedulerWhenRedisDown(t *testing.T) {
|
func TestSchedulerWhenRedisDown(t *testing.T) {
|
||||||
|
17
server.go
17
server.go
@ -37,6 +37,9 @@ type Server struct {
|
|||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
|
|
||||||
broker base.Broker
|
broker base.Broker
|
||||||
|
// When a Server has been created with an existing Redis connection, we do
|
||||||
|
// not want to close it.
|
||||||
|
sharedConnection bool
|
||||||
|
|
||||||
state *serverState
|
state *serverState
|
||||||
|
|
||||||
@ -428,10 +431,19 @@ const (
|
|||||||
// NewServer returns a new Server given a redis connection option
|
// NewServer returns a new Server given a redis connection option
|
||||||
// and server configuration.
|
// and server configuration.
|
||||||
func NewServer(r RedisConnOpt, cfg Config) *Server {
|
func NewServer(r RedisConnOpt, cfg Config) *Server {
|
||||||
c, ok := r.MakeRedisClient().(redis.UniversalClient)
|
redisClient, ok := r.MakeRedisClient().(redis.UniversalClient)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("asynq: unsupported RedisConnOpt type %T", r))
|
panic(fmt.Sprintf("asynq: unsupported RedisConnOpt type %T", r))
|
||||||
}
|
}
|
||||||
|
server := NewServerFromRedisClient(redisClient, cfg)
|
||||||
|
server.sharedConnection = false
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServerFromRedisClient returns a new Server given a redis client
|
||||||
|
// and server configuration.
|
||||||
|
// Warning: the redis client will not be closed by Asynq, you are responsible for closing.
|
||||||
|
func NewServerFromRedisClient(c redis.UniversalClient, cfg Config) *Server {
|
||||||
baseCtxFn := cfg.BaseContext
|
baseCtxFn := cfg.BaseContext
|
||||||
if baseCtxFn == nil {
|
if baseCtxFn == nil {
|
||||||
baseCtxFn = context.Background
|
baseCtxFn = context.Background
|
||||||
@ -595,6 +607,7 @@ func NewServer(r RedisConnOpt, cfg Config) *Server {
|
|||||||
return &Server{
|
return &Server{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
broker: rdb,
|
broker: rdb,
|
||||||
|
sharedConnection: true,
|
||||||
state: srvState,
|
state: srvState,
|
||||||
forwarder: forwarder,
|
forwarder: forwarder,
|
||||||
processor: processor,
|
processor: processor,
|
||||||
@ -732,7 +745,9 @@ func (srv *Server) Shutdown() {
|
|||||||
srv.heartbeater.shutdown()
|
srv.heartbeater.shutdown()
|
||||||
srv.wg.Wait()
|
srv.wg.Wait()
|
||||||
|
|
||||||
|
if !srv.sharedConnection {
|
||||||
srv.broker.Close()
|
srv.broker.Close()
|
||||||
|
}
|
||||||
srv.logger.Info("Exiting")
|
srv.logger.Info("Exiting")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,22 +14,12 @@ import (
|
|||||||
"github.com/hibiken/asynq/internal/rdb"
|
"github.com/hibiken/asynq/internal/rdb"
|
||||||
"github.com/hibiken/asynq/internal/testbroker"
|
"github.com/hibiken/asynq/internal/testbroker"
|
||||||
"github.com/hibiken/asynq/internal/testutil"
|
"github.com/hibiken/asynq/internal/testutil"
|
||||||
|
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServer(t *testing.T) {
|
func testServer(t *testing.T, c *Client, srv *Server) {
|
||||||
// https://github.com/go-redis/redis/issues/1029
|
|
||||||
ignoreOpt := goleak.IgnoreTopFunction("github.com/redis/go-redis/v9/internal/pool.(*ConnPool).reaper")
|
|
||||||
defer goleak.VerifyNone(t, ignoreOpt)
|
|
||||||
|
|
||||||
redisConnOpt := getRedisConnOpt(t)
|
|
||||||
c := NewClient(redisConnOpt)
|
|
||||||
defer c.Close()
|
|
||||||
srv := NewServer(redisConnOpt, Config{
|
|
||||||
Concurrency: 10,
|
|
||||||
LogLevel: testLogLevel,
|
|
||||||
})
|
|
||||||
|
|
||||||
// no-op handler
|
// no-op handler
|
||||||
h := func(ctx context.Context, task *Task) error {
|
h := func(ctx context.Context, task *Task) error {
|
||||||
return nil
|
return nil
|
||||||
@ -53,6 +43,43 @@ func TestServer(t *testing.T) {
|
|||||||
srv.Shutdown()
|
srv.Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServer(t *testing.T) {
|
||||||
|
// https://github.com/go-redis/redis/issues/1029
|
||||||
|
ignoreOpt := goleak.IgnoreTopFunction("github.com/redis/go-redis/v9/internal/pool.(*ConnPool).reaper")
|
||||||
|
defer goleak.VerifyNone(t, ignoreOpt)
|
||||||
|
|
||||||
|
redisConnOpt := getRedisConnOpt(t)
|
||||||
|
c := NewClient(redisConnOpt)
|
||||||
|
defer c.Close()
|
||||||
|
srv := NewServer(redisConnOpt, Config{
|
||||||
|
Concurrency: 10,
|
||||||
|
LogLevel: testLogLevel,
|
||||||
|
})
|
||||||
|
|
||||||
|
testServer(t, c, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServerFromRedisClient(t *testing.T) {
|
||||||
|
// https://github.com/go-redis/redis/issues/1029
|
||||||
|
ignoreOpt := goleak.IgnoreTopFunction("github.com/redis/go-redis/v9/internal/pool.(*ConnPool).reaper")
|
||||||
|
defer goleak.VerifyNone(t, ignoreOpt)
|
||||||
|
|
||||||
|
redisConnOpt := getRedisConnOpt(t)
|
||||||
|
redisClient := redisConnOpt.MakeRedisClient().(redis.UniversalClient)
|
||||||
|
c := NewClientFromRedisClient(redisClient)
|
||||||
|
srv := NewServerFromRedisClient(redisClient, Config{
|
||||||
|
Concurrency: 10,
|
||||||
|
LogLevel: testLogLevel,
|
||||||
|
})
|
||||||
|
|
||||||
|
testServer(t, c, srv)
|
||||||
|
|
||||||
|
err := c.Close()
|
||||||
|
if err == nil {
|
||||||
|
t.Error("client.Close() should have failed because of a shared client but it didn't")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestServerRun(t *testing.T) {
|
func TestServerRun(t *testing.T) {
|
||||||
// https://github.com/go-redis/redis/issues/1029
|
// https://github.com/go-redis/redis/issues/1029
|
||||||
ignoreOpt := goleak.IgnoreTopFunction("github.com/redis/go-redis/v9/internal/pool.(*ConnPool).reaper")
|
ignoreOpt := goleak.IgnoreTopFunction("github.com/redis/go-redis/v9/internal/pool.(*ConnPool).reaper")
|
||||||
|
Loading…
Reference in New Issue
Block a user