Set dependency to Response when multi in pipeline and build dependency

first if Response's dependency found and not built

* there's some dependency with exec response and command responses
within multi
* if command responses's get() called before exec response's build(), it
calls exec response's build() first
* unit test included
This commit is contained in:
Jungtaek Lim
2014-02-17 13:37:06 +09:00
parent b2fa6b6c40
commit 68ee4e49d0
3 changed files with 54 additions and 8 deletions

View File

@@ -31,6 +31,12 @@ public class Pipeline extends MultiKeyPipelineBase {
return values;
}
public void setResponseDependency(Response<?> dependency) {
for (Response<?> response : responses) {
response.setDependency(dependency);
}
}
public void addResponse(Response<?> response) {
responses.add(response);
}
@@ -106,6 +112,7 @@ public class Pipeline extends MultiKeyPipelineBase {
public Response<List<Object>> exec() {
client.exec();
Response<List<Object>> response = super.getResponse(currentMulti);
currentMulti.setResponseDependency(response);
currentMulti = null;
return response;
}

View File

@@ -8,6 +8,8 @@ public class Response<T> {
private boolean set = false;
private Builder<T> builder;
private Object data;
private Response<?> dependency = null;
private boolean requestDependencyBuild = false;
public Response(Builder<T> b) {
this.builder = b;
@@ -19,23 +21,39 @@ public class Response<T> {
}
public T get() {
// if response has dependency response and dependency is not built,
// build it first and no more!!
if (!requestDependencyBuild && dependency != null && dependency.set
&& !dependency.built) {
requestDependencyBuild = true;
dependency.build();
}
if (!set) {
throw new JedisDataException(
"Please close pipeline or multi block before calling this method.");
}
if (!built) {
if (data != null) {
if (data instanceof JedisDataException) {
throw new JedisDataException((JedisDataException) data);
}
response = builder.build(data);
}
this.data = null;
built = true;
build();
}
return response;
}
public void setDependency(Response<?> dependency) {
this.dependency = dependency;
this.requestDependencyBuild = false;
}
private void build() {
if (data != null) {
if (data instanceof JedisDataException) {
throw new JedisDataException((JedisDataException) data);
}
response = builder.build(data);
}
data = null;
built = true;
}
public String toString() {
return "Response " + builder.toString();
}

View File

@@ -251,6 +251,27 @@ public class PipeliningTest extends Assert {
}
@Test
public void multiWithSync() {
jedis.set("foo", "314");
jedis.set("bar", "foo");
jedis.set("hello", "world");
Pipeline p = jedis.pipelined();
Response<String> r1 = p.get("bar");
p.multi();
Response<String> r2 = p.get("foo");
p.exec();
Response<String> r3 = p.get("hello");
p.sync();
// before multi
assertEquals("foo", r1.get());
// It should be readable whether exec's response was built or not
assertEquals("314", r2.get());
// after multi
assertEquals("world", r3.get());
}
@Test
public void testDiscardInPipeline() {
Pipeline pipeline = jedis.pipelined();