This repository has been archived by the owner on May 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bugfix: catch and rethrow BlockingOperationException for batchSet (#51)
- Loading branch information
Wu Tao
authored and
neverchanje
committed
Sep 24, 2019
1 parent
92a82c5
commit 4e40054
Showing
5 changed files
with
127 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
dist: trusty | ||
|
||
language: java | ||
|
||
jdk: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
src/main/java/com/xiaomi/infra/pegasus/client/FutureGroup.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. | ||
// This source code is licensed under the Apache License Version 2.0, which | ||
// can be found in the LICENSE file in the root directory of this source tree. | ||
package com.xiaomi.infra.pegasus.client; | ||
|
||
import io.netty.util.concurrent.Future; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
final class FutureGroup<Result> { | ||
|
||
FutureGroup(int initialCapacity) { | ||
asyncTasks = new ArrayList<>(initialCapacity); | ||
} | ||
|
||
public void add(Future<Result> task) { | ||
asyncTasks.add(task); | ||
} | ||
|
||
void waitAllCompleteOrOneFail(int timeoutMillis) throws PException { | ||
waitAllCompleteOrOneFail(null, timeoutMillis); | ||
} | ||
|
||
// Waits until all future tasks complete but terminate if one fails. | ||
// `results` is nullable | ||
void waitAllCompleteOrOneFail(List<Result> results, int timeoutMillis) throws PException { | ||
for (int i = 0; i < asyncTasks.size(); i++) { | ||
Future<Result> fu = asyncTasks.get(i); | ||
try { | ||
fu.await(timeoutMillis); | ||
} catch (Exception e) { | ||
throw new PException("async task #[" + i + "] await failed: " + e.toString()); | ||
} | ||
if (fu.isSuccess()) { | ||
if (results != null) { | ||
results.set(i, fu.getNow()); | ||
} | ||
} else { | ||
Throwable cause = fu.cause(); | ||
throw new PException("async task #[" + i + "] failed: " + cause.getMessage(), cause); | ||
} | ||
} | ||
} | ||
|
||
private List<Future<Result>> asyncTasks; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
src/test/java/com/xiaomi/infra/pegasus/client/TestFutureGroup.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. | ||
// This source code is licensed under the Apache License Version 2.0, which | ||
// can be found in the LICENSE file in the root directory of this source tree. | ||
package com.xiaomi.infra.pegasus.client; | ||
|
||
import io.netty.util.concurrent.Promise; | ||
import io.netty.util.concurrent.SingleThreadEventExecutor; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
public class TestFutureGroup { | ||
|
||
private static final class TestEventExecutor extends SingleThreadEventExecutor { | ||
TestEventExecutor() { | ||
super(null, Executors.defaultThreadFactory(), false); | ||
} | ||
|
||
@Override | ||
protected void run() { | ||
while (!confirmShutdown()) { | ||
Runnable task = takeTask(); | ||
if (task != null) { | ||
task.run(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
public void testBlockingOperationException() throws Exception { | ||
// ensure pegasus client will throw PException when BlockingOperationException is thrown. | ||
|
||
TestEventExecutor executor = new TestEventExecutor(); | ||
Promise<Void> promise = executor.newPromise(); | ||
AtomicBoolean executed = new AtomicBoolean(false); | ||
AtomicBoolean success = new AtomicBoolean(true); | ||
|
||
executor.execute( | ||
() -> { | ||
// A background thread waiting for promise to complete. | ||
FutureGroup<Void> group = new FutureGroup<>(1); | ||
group.add(promise); | ||
try { | ||
group.waitAllCompleteOrOneFail(10000); | ||
} catch (PException e) { | ||
success.set(false); | ||
System.err.println("TestFutureGroup.testInterrupt: " + e.toString()); | ||
} | ||
executed.set(true); | ||
}); | ||
|
||
while (executor.pendingTasks() != 0) { | ||
Thread.sleep(100); | ||
} | ||
|
||
promise.setSuccess(null); | ||
|
||
// block until the background thread finished. | ||
while (!executed.get()) { | ||
Thread.sleep(100); | ||
} | ||
|
||
Assert.assertFalse(success.get()); | ||
} | ||
} |