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

re-authenticate and re-select database when disconnect #101

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

timotta
Copy link

@timotta timotta commented Feb 12, 2014

When a client on a connection pool looses its connection to redis-server, is necessary to re-authenticate this client. The problem can be reproduced following these steps:

  1. Edit your redis-server to have requiredpass:
sudo vim /etc/redis/redis.conf
requirepass foobared
  1. Open sbt console and execute
import com.redis._
val p = new RedisClientPool("localhost", 6379, secret=Some("foobared"), maxIdle=1)
p.withClient { client => client.set("x","y") }
  1. Do not close console and restart redis
sudo service redis-server restart
  1. On the previously sbt console execute:
p.withClient { client => client.set("x","y") }
java.lang.Exception: NOAUTH Authentication required

The change in this commit correct this problem, re-authenticanting and re-selecting the redis database when connection was lost. Also, it includes a feature allowing single client to have database and authentication:

val r = new RedisClient("localhost", 6379, 0, Some("foobared"))

@debasishg
Copy link
Owner

Thanks a lot .. will do a review and merge over the weekend.

@timotta
Copy link
Author

timotta commented Feb 20, 2014

hi, any news on that?

@debasishg
Copy link
Owner

Apologies for the delay .. was awfully busy with day job. Will merge the PR this weekend for sure ..

@debasishg
Copy link
Owner

I was trying out the changes and getting a StackOverFlowError ..

Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_65).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import com.redis._
import com.redis._

scala> val p = new RedisClientPool("localhost", 6379, secret=Some("foobared"), maxIdle=1)
p: com.redis.RedisClientPool = localhost:6379

scala> p.withClient { client => client.set("x","y") }
log4j:WARN No appenders could be found for logger (com.redis.RedisClient).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
java.lang.RuntimeException: java.lang.StackOverflowError
    at com.redis.IO$class.connect(IO.scala:36)
    at com.redis.RedisClient.connect(RedisClient.scala:89)
    at com.redis.RedisCommandOperations$class.initialize(RedisClient.scala:60)
    at com.redis.RedisClient.initialize(RedisClient.scala:89)
    at com.redis.Redis$class.reconnect(RedisClient.scala:49)
    at com.redis.RedisClient.reconnect(RedisClient.scala:89)
    at com.redis.Reply$$anonfun$6.applyOrElse(RedisProtocol.scala:94)
    at com.redis.Reply$$anonfun$6.applyOrElse(RedisProtocol.scala:93)
    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:33)
    at com.redis.Reply$$anonfun$3.applyOrElse(RedisProtocol.scala:58)
    at com.redis.Reply$$anonfun$3.applyOrElse(RedisProtocol.scala:58)
    at scala.PartialFunction$OrElse.apply(PartialFunction.scala:162)
    at com.redis.Reply$$anonfun$1.applyOrElse(RedisProtocol.scala:48)
    at com.redis.Reply$$anonfun$1.applyOrElse(RedisProtocol.scala:48)
    at scala.PartialFunction$OrElse.apply(PartialFunction.scala:162)
    at com.redis.Reply$class.receive(RedisProtocol.scala:114)

@timotta
Copy link
Author

timotta commented Feb 22, 2014

Hi,

Im going to see what is happening until monday.

[]'s

Tiago Albineli Motta
Desenvolvedor de Software - Globo.com
ICQ: 32107100
http://programandosemcafeina.blogspot.com

On Sat, Feb 22, 2014 at 1:21 PM, Debasish Ghosh [email protected]:

I was trying out the changes and getting a StackOverFlowError ..

Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_65).Type in expressions to have them evaluated.Type :help for more information.
scala> import com.redis.import com.redis.
scala> val p = new RedisClientPool("localhost", 6379, secret=Some("foobared"), maxIdle=1)p: com.redis.RedisClientPool = localhost:6379
scala> p.withClient { client => client.set("x","y") }log4j:WARN No appenders could be found for logger (com.redis.RedisClient).log4j:WARN Please initialize the log4j system properly.log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.java.lang.RuntimeException: java.lang.StackOverflowError
at com.redis.IO$class.connect(IO.scala:36)
at com.redis.RedisClient.connect(RedisClient.scala:89)
at com.redis.RedisCommandOperations$class.initialize(RedisClient.scala:60)
at com.redis.RedisClient.initialize(RedisClient.scala:89)
at com.redis.Redis$class.reconnect(RedisClient.scala:49)
at com.redis.RedisClient.reconnect(RedisClient.scala:89)
at com.redis.Reply$$anonfun$6.applyOrElse(RedisProtocol.scala:94)
at com.redis.Reply$$anonfun$6.applyOrElse(RedisProtocol.scala:93)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:33)
at com.redis.Reply$$anonfun$3.applyOrElse(RedisProtocol.scala:58)
at com.redis.Reply$$anonfun$3.applyOrElse(RedisProtocol.scala:58)
at scala.PartialFunction$OrElse.apply(PartialFunction.scala:162)
at com.redis.Reply$$anonfun$1.applyOrElse(RedisProtocol.scala:48)
at com.redis.Reply$$anonfun$1.applyOrElse(RedisProtocol.scala:48)
at scala.PartialFunction$OrElse.apply(PartialFunction.scala:162)
at com.redis.Reply$class.receive(RedisProtocol.scala:114)

Reply to this email directly or view it on GitHubhttps://github.com//pull/101#issuecomment-35806572
.

@debasishg
Copy link
Owner

cool .. I will merge it once I hear from you ..

@timotta
Copy link
Author

timotta commented Feb 22, 2014

The problem happens when a redis-server is not configured to have password
and you try to connect using password.

In this redis-server returns an error, and we try to reconnect. The
reconnect function tries to auth agains, redis-server returns an error ...
and go go go overflow.

So now, im changing auth to use another send command that only reconnects,
without reauth, when receiveing error from server. I will close the old
pull request and send another with two commits Ok?

Tiago Albineli Motta
Desenvolvedor de Software - Globo.com
ICQ: 32107100
http://programandosemcafeina.blogspot.com

On Sat, Feb 22, 2014 at 1:40 PM, Debasish Ghosh [email protected]:

cool .. I will merge it once I hear from you ..

Reply to this email directly or view it on GitHubhttps://github.com//pull/101#issuecomment-35807112
.

@debasishg
Copy link
Owner

+1 .. will wait for the new PR ..

@timotta
Copy link
Author

timotta commented Feb 22, 2014

@debasishg i anexed to this pull request the other commit. It's ok for you?

Without password on redis-server:

scala> val p = new RedisClientPool("localhost", 6379, secret=Some("foobared"), maxIdle=1)
scala> p.withClient { client => client.set("x","y") }
java.lang.Exception: ERR Client sent AUTH, but no password is set
scala> val p = new RedisClientPool("localhost", 6379, secret=None, maxIdle=1)
scala> p.withClient { client => client.set("x","y") }
res2: Boolean = true

With password on redis-server:

scala> val p = new RedisClientPool("localhost", 6379, secret=Some("foobared"), maxIdle=1)
scala> p.withClient { client => client.set("x","y") }
res1: Boolean = true
scala> val p = new RedisClientPool("localhost", 6379, secret=None, maxIdle=1)
scala> p.withClient { client => client.set("x","y") }
java.lang.Exception: NOAUTH Authentication required.

@debasishg
Copy link
Owner

Thanks for the fix. I did apply it and verified that it works. Then I noticed some code duplication between send and sendWithoutAuth, which I thought should be addressed. I did make some changes on top of your latest commit and put it in the branch auth-fix (https://github.com/debasishg/scala-redis/commits/auth-fix). Please have a look. Once I hear from you I will cherry-pick it into master.

@timotta
Copy link
Author

timotta commented Feb 25, 2014

Great.

The only problem is that it looks like now the "initialize" method only selectDatabase when there is a secret defined. It is not the correct behavior.

Maybe we show let this part like before:

     selectDatabase
     authenticate

@debasishg
Copy link
Owner

Ok .. made that change in branch auth-fix .. now ready for the final release.

@lahirug
Copy link

lahirug commented Aug 9, 2015

Do you support reconnect and recover subscriptions ?

@debasishg
Copy link
Owner

No, it's not supported as of now. I need to work on this PR and check if this can make to master. Horribly out of time these days. I will try over the coming weekend.

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

Successfully merging this pull request may close these issues.

3 participants