Fix SRP exec not returning results of commands

executed in the tx

DATAREDIS-123

- Close pipeline on exec if not explicitly
opened by user and return results of closePipeline,
not result of exec command

- Close pipeline on discard if not explicitly
opened by user
This commit is contained in:
Jennifer Hickey
2013-04-04 20:46:08 -07:00
parent 7813a13f7a
commit aaa28495be
8 changed files with 268 additions and 78 deletions

View File

@@ -61,6 +61,7 @@ public class SrpConnection implements RedisConnection {
private boolean isClosed = false;
private boolean isMulti = false;
private boolean pipelineRequested = false;
private Pipeline pipeline;
private PipelineTracker callback;
private volatile SrpSubscription subscription;
@@ -173,42 +174,14 @@ public class SrpConnection implements RedisConnection {
public void openPipeline() {
if (pipeline == null) {
callback = new PipelineTracker();
pipeline = client.pipeline();
}
pipelineRequested = true;
initPipeline();
}
public List<Object> closePipeline() {
if (pipeline != null) {
pipeline = null;
List<Object> execute = new ArrayList<Object>(callback.complete());
callback.close();
callback = null;
if (execute != null && !execute.isEmpty()) {
Exception cause = null;
for (int i = 0; i < execute.size(); i++) {
Object object = execute.get(i);
if (object instanceof Exception) {
DataAccessException dataAccessException = convertSrpAccessException((Exception) object);
if (cause == null) {
cause = dataAccessException;
}
execute.set(i, dataAccessException);
}
}
if (cause != null) {
throw new RedisPipelineException(cause, execute);
}
return execute;
}
}
return Collections.emptyList();
return closePipeline(true);
}
public List<byte[]> sort(byte[] key, SortParameters params) {
byte[] sort = SrpUtils.sort(params);
@@ -440,11 +413,10 @@ public class SrpConnection implements RedisConnection {
public void discard() {
isMulti = false;
try {
if (isPipelined()) {
// use the normal path
}
client.discard();
if (!pipelineRequested) {
closePipeline(false);
}
} catch (Exception ex) {
throw convertSrpAccessException(ex);
}
@@ -455,10 +427,12 @@ public class SrpConnection implements RedisConnection {
isMulti = false;
try {
Future<Boolean> exec = client.exec();
if (!isPipelined()) {
exec.get();
// Need to wait on execution or subsequent non-pipelined calls like multi may read exec results
exec.get();
if (pipelineRequested) {
return null;
}
return Collections.singletonList((Object) exec);
return closePipeline();
} catch (Exception ex) {
throw convertSrpAccessException(ex);
}
@@ -522,12 +496,8 @@ public class SrpConnection implements RedisConnection {
return;
}
isMulti = true;
openPipeline();
initPipeline();
try {
if (isPipelined()) {
client.multi();
return;
}
client.multi();
} catch (Exception ex) {
throw convertSrpAccessException(ex);
@@ -1899,4 +1869,48 @@ public class SrpConnection implements RedisConnection {
private void pipeline(ListenableFuture<? extends Reply> future) {
callback.addCommand(future);
}
private void initPipeline() {
if (pipeline == null) {
callback = new PipelineTracker();
pipeline = client.pipeline();
}
}
private List<Object> closePipeline(boolean getResults) {
pipelineRequested = false;
List<Object> results = Collections.emptyList();
if (pipeline != null) {
pipeline = null;
if(getResults) {
results = getPipelinedResults();
}
callback.close();
callback = null;
}
return results;
}
private List<Object> getPipelinedResults() {
List<Object> execute = new ArrayList<Object>(callback.complete());
if (execute != null && !execute.isEmpty()) {
Exception cause = null;
for (int i = 0; i < execute.size(); i++) {
Object object = execute.get(i);
if (object instanceof Exception) {
DataAccessException dataAccessException = convertSrpAccessException((Exception) object);
if (cause == null) {
cause = dataAccessException;
}
execute.set(i, dataAccessException);
}
}
if (cause != null) {
throw new RedisPipelineException(cause, execute);
}
return execute;
}
return Collections.emptyList();
}
}