redis transaction with multi/exec

13 views
Skip to first unread message

Alan Malloy

unread,
Jun 14, 2011, 6:33:24 PM6/14/11
to Aleph
I'm trying to perform some redis transactions with the aleph client; I
have to do a couple operations atomically, and I have multiple threads
each playing with their own redis client. It should be a simple matter
of sending :multi, some commands, and then :exec - aleph doesn't even
have to know anything about how they work.

But transactions seem to work sometimes and not other times, and I
can't really track down what causes them to break; when they do,
the :exec call hangs forever (or times out, if I've set a timeout).
Here's an example of them not working, from my repl:

graph.mbox> (def rcli @redis) ;; thread-local fn, passing 1-sec
timeout
#'graph.mbox/rcli
graph.mbox> @(rcli [:keys "*"])
()
graph.mbox> @(rcli [:multi])
"OK"
graph.mbox> @(rcli [:keys "*"])
"QUEUED"
graph.mbox> @(rcli [:exec])
; Evaluation aborted.

Is this a known issue, or familiar to someone? If not, feel free to
tell me what additional information is required to debug the issue.

Thanks,
~Alan

ztellman

unread,
Jun 14, 2011, 7:14:44 PM6/14/11
to Aleph
Do you ever get a response telling you that the EXEC command has
failed? It's possible that the error response isn't being handled
correctly.

Zach

Alan Malloy

unread,
Jun 14, 2011, 7:23:10 PM6/14/11
to Aleph
I don't think I know enough about aleph to answer this question; so
far it's just a redis client to me. If I (def resp @(rcli [:exec])),
and then look at resp a few times in the repl, it prints as << ... >>
for a while, until the timeout expires; at that point it starts
behaving like:

graph.mbox> resp
<< ERROR: java.util.concurrent.TimeoutException: Timed out after
20000ms. >>
graph.mbox> @resp
; Evaluation aborted.

Is there something else I should do to answer your question?

Alan Malloy

unread,
Jun 14, 2011, 7:30:04 PM6/14/11
to Aleph
Sorry, @ there was a mistake. I am running (def resp (rcli [:exec])),
otherwise the rest of my story probably makes little sense.

ztellman

unread,
Jun 14, 2011, 7:45:07 PM6/14/11
to Aleph
I think I've located the issue. There appears to have been a
regression in lamina.connections w.r.t. error handling. In the case
that there's an exception as a result of a connectivity issue, it will
re-send the request. However, now *all* exceptions are being treated
as connectivity errors, so if the EXEC command fails it will be
continually resent. You can get similar behavior by just sending :get
to Redis without any arguments.

I should have this fixed soon.

Zach

Zach Tellman

unread,
Jun 14, 2011, 7:59:10 PM6/14/11
to Aleph
Okay, a fix has been checked into the 'new' branch of Lamina, and
pushed to clojars as 0.2.0-alpha3-SNAPSHOT. I haven't reproduced your
exact issue with intermittent failures with EXEC, but there was a
definite issue with Redis errors so I'm pretty certain this will fix
the behavior you were seeing. If you're still seeing it, let me know.

Zach

Alan Malloy

unread,
Jun 14, 2011, 9:14:48 PM6/14/11
to Aleph
Still seeing the same behavior with aleph-0.2.0-
alpha3-20110601.165758-2.jar in my lib/ directory.

I think my vague ramblings about "intermittent" were misleading: some
{multi=>whatever=>exec} sequences always work and some always fail,
but I have trouble predicting whether a given one will fail. I
wouldn't waste time tracking those down; it's probably either caused
by whatever causing the current problem or else by my sending illegal
redis commands.

Alan Malloy

unread,
Jun 14, 2011, 9:18:00 PM6/14/11
to Aleph
Here's a simple script I can reproduce with, that doesn't depend on my
silly thread-local construction of redis clients:

https://gist.github.com/1026298

graph.mbox> (def rcli (let [client (redis/redis-client {:host
"localhost"})]
(fn [command] (client command 20000))))
#'graph.mbox/rcli
graph.mbox> @(rcli [:multi])
"OK"
graph.mbox> @(rcli [:keys "*"])
"QUEUED"
graph.mbox> @(rcli [:exec])
; Evaluation aborted.

On Jun 14, 4:59 pm, Zach Tellman <ztell...@gmail.com> wrote:

ztellman

unread,
Jun 14, 2011, 11:04:15 PM6/14/11
to Aleph
Okay, I figured it out. Redis has multiple kinds of responses, but
the most general one is a multi-bulk statement, which is prepended by
a number that I understood to describe the number of statements that
followed. What I didn't foresee was the possibility that one of those
statements might themselves be a multi-bulk statement (like your "KEYS
*" command), and so it wasn't able to successfully parse that
response.

I've pushed a fix for this, again under alpha3-SNAPSHOT. Thanks for
the report, and for finding a simple example of the problem. Your
issue appears to have nothing to do with the error handling bug I
found, but it's a nice bonus that this led me to discover it.

Let me know if you have any other issues.

Zach

Alan Malloy

unread,
Jun 15, 2011, 1:29:48 AM6/15/11
to Aleph
Thanks. I'll confirm the fix when I get to work tomorrow.

Alan Malloy

unread,
Jun 15, 2011, 12:56:36 PM6/15/11
to Aleph
Works splendidly, both for my simplified test case and my actual
usage. Thanks.
Reply all
Reply to author
Forward
0 new messages