Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement reusing redis client #742

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jerbob92
Copy link

This PR allows you to re-use an existing Redis client with Asynq, this gives you the benifit of less Redis connections and more control over the Redis configuration options since Asynq doesn't provide all the options.

@jerbob92 jerbob92 force-pushed the feature/implement-reusing-redis-client branch 2 times, most recently from 0d583af to a89a3ac Compare September 19, 2023 08:40
@kamikazechaser
Copy link
Collaborator

This is already possible without any changes to asynq: https://pkg.go.dev/github.com/hibiken/asynq?utm_source=godoc#RedisConnOpt

E.g.

package pool

type (
	SharedRedisPoolOpts struct {
		DSN          string
		MinIdleConns int
	}

	SharedRedisPool struct {
		Client *redis.Client
	}
)

func NewSharedRedisPool(o SharedRedisPoolOpts) (*SharedRedisPool, error) {
	redisOpts, err := redis.ParseURL(o.DSN)
	if err != nil {
		return nil, err
	}

	redisOpts.MinIdleConns = o.MinIdleConns
	redisClient := redis.NewClient(redisOpts)

	return &SharedRedisPool{
		Client: redisClient,
	}, nil
}

// Fulfills asynq's Interface
func (r *SharedRedisPool) MakeRedisClient() interface{} {
	return r.Client
}

// Somewhere else when creating an asynq server asynq.NewServer()
// use *pool.SharedRedisPool

@jerbob92
Copy link
Author

Thanks! I knew it is already possible but it's not really that clear to users how they can do it and it doesn't protect you against accidental closing of the client.

@kamikazechaser
Copy link
Collaborator

how they can do it

Right, it is not documented in the wiki. Maybe it should be added there.

doesn't protect you against accidental closing of the client.

True.

Btw looks like some tests are failing.

@jerbob92 jerbob92 force-pushed the feature/implement-reusing-redis-client branch from a89a3ac to 1890659 Compare September 19, 2023 09:15
@jerbob92 jerbob92 force-pushed the feature/implement-reusing-redis-client branch from 1890659 to 9e548fc Compare September 19, 2023 09:20
@codecov
Copy link

codecov bot commented Sep 19, 2023

Codecov Report

Attention: 2 lines in your changes are missing coverage. Please review.

Comparison is base (6a7bf2c) 68.37% compared to head (9e548fc) 68.49%.

Files Patch % Lines
inspector.go 71.42% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #742      +/-   ##
==========================================
+ Coverage   68.37%   68.49%   +0.11%     
==========================================
  Files          27       27              
  Lines        3836     3856      +20     
==========================================
+ Hits         2623     2641      +18     
- Misses        929      930       +1     
- Partials      284      285       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jerbob92
Copy link
Author

jerbob92 commented Sep 19, 2023

Btw looks like some tests are failing.

Yep, fixed!

Copy link
Collaborator

@kamikazechaser kamikazechaser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some feedback on godocs and the Scheduler shutdown behavior with this change.

return inspector
}

// NewFromRedisClient returns a new instance of Inspector.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// NewInspectorFromRedisClient returns a new instance of Inspector given a redis.UniversalClient
// Warning: The underlying redis connection pool will not be closed by Asynq, you are responsible for closing it.

}

// 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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// NewClientFromRedisClient returns a new instance of Client given a redis.UniversalClient
// Warning: The underlying redis connection pool will not be closed by Asynq, you are responsible for closing it.

return scheduler
}

// NewSchedulerFromRedisClient returns a new Scheduler instance given a redis client.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// NewSchedulerFromRedisClient returns a new instance of Scheduler given a redis.UniversalClient
// The parameter opts is optional, defaults will be used if opts is set to nil.
// Warning: The underlying redis connection pool will not be closed by Asynq, you are responsible for closing it.

@@ -262,7 +274,9 @@ func (s *Scheduler) Shutdown() {

s.clearHistory()
s.client.Close()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of scheduler.Shutdown, the client is closed by Asynq. If it uses a shared pool, it will return an error (which is unhandled here). Perhaps it should be moved to the following if clause?

If the scheduler ends up using a shared redis connection pool, perhaps it should only be stopped. Right now there doesn't seem to be an option to simply Stop/Pause the scheduler though

return server
}

// NewServerFromRedisClient returns a new Server given a redis client
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// NewServerFromRedisClient returns a new instance of Server given a redis.UniversalClient
// and server configuration
// Warning: The underlying redis connection pool will not be closed by Asynq, you are responsible for closing it.

@kamikazechaser
Copy link
Collaborator

kamikazechaser commented May 6, 2024

@jerbob92 This is ready to be merged. Could you update the inline docs (as per the suggestions) so that we have a uniform outlook. Thanks.

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

Successfully merging this pull request may close these issues.

2 participants