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

Can't set up multiple JedisBundles in the same DropWizard application #40

Open
vasukisesh opened this issue Jun 23, 2017 · 9 comments
Open

Comments

@vasukisesh
Copy link
Collaborator

I'd like to be able to use multiple JedisBundles (to connect to multiple Redis instances) from the same DropWizard application. I think this is not currently possible/supported. I wonder if it's just because of the name "redis" being hardcoded in the JedisBundle class for healthcheck and metrics? Or is there some deeper reason? If it is the former, should be easy enough to get that value from a protected "getName()" method that can be overridden for multiple bundles.

@benjamin-bader
Copy link
Owner

It isn't currently supported, but there's no deeper reason why not. I never had the need, and neither has anyone else (at least, nobody who wanted it enough to let me know, until now!). It's a reasonable thing to want to do.

I think your hunch is correct - "redis" is indeed hardcoded for metrics and healthchecks, which won't work for multiple connections. Connection names could follow, e.g. instead of "redis.connections.idle" we could have "redis.readonly.connections.idle".

The bigger question for me would be the API to choose which of the connections you want to inject into resource methods. I haven't used Dropwizard for a long time now; my knowledge is mostly for Jersey 1.x, which hasn't been in use in DW since like 2014, I think. I'd appreciate any ideas you have.

Say you had "readonly" and "leader" connections. Simple @Context annotations are not sufficient to distinguish between them. What would the right API look like?

@vasukisesh
Copy link
Collaborator Author

vasukisesh commented Jun 26, 2017

Hmm, good question. We use Guice injection in our codebase, so we haven't had the need to use @Context. I'll have to think about that some more. Thanks for the quick response!

@vasukisesh
Copy link
Collaborator Author

I'm not very familiar with HK2, but I wonder if this could be achieved by using named injection. I don't know if @Named can be used with @Context. If so, it should be easy to bind two different JedisPools by using .named(...) in the binding. Thoughts?

@imarban
Copy link

imarban commented Jul 16, 2018

@vasukisesh Are you using this project along with Guice injection? How did you manage to be able to inject Jedis instances not using @Context annotation? Thanks!

@benjamin-bader
Copy link
Owner

When you're setting up your Guice modules, give one of them the pool object from your JedisBundle implementation, and have it bind the pool as a singleton instance. Lifecycle issues makes this a bit tricky, since you won't have the pool until your application's run method (i.e. not during initialization).

@imarban
Copy link

imarban commented Jul 16, 2018

@benjamin-bader But, then you have to get resources from the pool as needed, right? Using a try-with resources every time or am I missing something?

@benjamin-bader
Copy link
Owner

Basically, unless you can find a way to (for example) configure request-scoped injection such that a connection is obtained from the pool, then destroyed when the scope ends. I haven't used guice personally in a very long time, so I don't know how to do this or even if it is possible.

Generally, try-with-resources isn't too burdensome, and as your application grows its weight will be negligible. @Context-injection is really only appropriate for the smallest of microservices; usually, your request handler isn't going to be aware of things like redis connections. That's usually the job of a Repository of some sort.

@vasukisesh
Copy link
Collaborator Author

Sorry for the delay in replying, but I've been on vacation. Yes, we basically did what @benjamin-bader has suggested above. We pass the JedisBundle reference into the constructor of our Guice module and then bind JedisPool.class to the pool from the bundle in the module's configure method by which point the pool is available. Using the dropwizard-guicey library helps get around much of the lifecycle issues.

As for your second question, again @benjamin-bader is correct. You should be using try-with-resources every time you need a connection the pool. That is the preferred method of using Jedis anyway. You can use a RequestScoped bean to create your connection but I wouldn't recommend it. We have a layer of abstraction in our service that handles all the Redis communication and it "hides" the connection management from the caller.

@imarban
Copy link

imarban commented Jul 18, 2018

@vasukisesh Thanks for your response. Yeah, the other way around didn't seem very well designed. So, I took your approach.

@benjamin-bader Thanks for your help.

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

No branches or pull requests

3 participants