Skip to content

Commit 8362063

Browse files
committed
Java 8 version: replace FutureImpl with CompletableFuture and add composable version of async interface via CompletionStage
1 parent 3c39e85 commit 8362063

File tree

5 files changed

+46
-115
lines changed

5 files changed

+46
-115
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,11 @@ TarantoolClient client = new TarantoolClientImpl(socketChannelProvider, config);
7474
> resolution, you could create a function that returns necessary name-to-ID
7575
> mappings.
7676
77-
`TarantoolClient` provides three interfaces to execute queries:
77+
`TarantoolClient` provides four interfaces to execute queries:
7878

7979
* `SyncOps` - returns the operation result
8080
* `AsyncOps` - returns the operation result as a `Future`
81+
* `ComposableAsyncOps`- return the operation result as a `CompletionStage`
8182
* `FireAndForgetOps` - returns the query ID
8283

8384
Feel free to override any method of `TarantoolClientImpl`. For example, to hook

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737
<plugin>
3838
<groupId>org.apache.maven.plugins</groupId>
3939
<artifactId>maven-compiler-plugin</artifactId>
40-
<version>3.2</version>
40+
<version>3.7.0</version>
4141
<configuration>
42-
<source>1.6</source>
43-
<target>1.6</target>
42+
<source>1.8</source>
43+
<target>1.8</target>
4444
</configuration>
4545
</plugin>
4646
</plugins>

src/main/java/org/tarantool/FutureImpl.java

Lines changed: 0 additions & 94 deletions
This file was deleted.

src/main/java/org/tarantool/TarantoolClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.tarantool;
22

33
import java.util.List;
4+
import java.util.concurrent.CompletionStage;
45
import java.util.concurrent.Future;
56
import java.util.concurrent.TimeUnit;
67

@@ -9,6 +10,8 @@ public interface TarantoolClient {
910

1011
TarantoolClientOps<Integer, List<?>, Object, Future<List<?>>> asyncOps();
1112

13+
TarantoolClientOps<Integer, List<?>, Object, CompletionStage<List<?>>> composableAsyncOps();
14+
1215
TarantoolClientOps<Integer, List<?>, Object, Long> fireAndForgetOps();
1316

1417
void close();

src/main/java/org/tarantool/TarantoolClientImpl.java

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import java.util.Iterator;
99
import java.util.List;
1010
import java.util.Map;
11+
import java.util.concurrent.CompletableFuture;
12+
import java.util.concurrent.CompletionStage;
1113
import java.util.concurrent.ConcurrentHashMap;
1214
import java.util.concurrent.CountDownLatch;
1315
import java.util.concurrent.ExecutionException;
@@ -31,7 +33,7 @@ public class TarantoolClientImpl extends TarantoolBase<Future<List<?>>> implemen
3133
protected volatile Exception thumbstone;
3234
protected volatile CountDownLatch alive;
3335

34-
protected Map<Long, FutureImpl<List<?>>> futures;
36+
protected Map<Long, CompletableFuture<List<?>>> futures;
3537
protected AtomicInteger wait = new AtomicInteger();
3638
/**
3739
* Write properties
@@ -49,6 +51,7 @@ public class TarantoolClientImpl extends TarantoolBase<Future<List<?>>> implemen
4951
*/
5052
protected SyncOps syncOps;
5153
protected FireAndForgetOps fireAndForgetOps;
54+
protected ComposableAsyncOps composableAsyncOps;
5255

5356
/**
5457
* Inner
@@ -77,7 +80,7 @@ public TarantoolClientImpl(SocketChannelProvider socketProvider, TarantoolClient
7780
this.alive = new CountDownLatch(1);
7881
this.socketProvider = socketProvider;
7982
this.stats = new TarantoolClientStats();
80-
this.futures = new ConcurrentHashMap<Long, FutureImpl<List<?>>>(config.predictedFutures);
83+
this.futures = new ConcurrentHashMap<>(config.predictedFutures);
8184
this.sharedBuffer = ByteBuffer.allocateDirect(config.sharedBufferSize);
8285
this.writerBuffer = ByteBuffer.allocateDirect(sharedBuffer.capacity());
8386
this.connector.setDaemon(true);
@@ -197,21 +200,22 @@ protected void configureThreads(String threadName) {
197200
}
198201

199202

200-
public Future<List<?>> exec(Code code, Object... args) {
203+
public CompletableFuture<List<?>> exec(Code code, Object... args) {
201204
validateArgs(args);
202-
FutureImpl<List<?>> q = new FutureImpl<List<?>>(syncId.incrementAndGet());
205+
long sid = syncId.incrementAndGet();
206+
CompletableFuture<List<?>> q = new CompletableFuture<>();
203207
if (isDead(q)) {
204208
return q;
205209
}
206-
futures.put(q.getId(), q);
210+
futures.put(sid, q);
207211
if (isDead(q)) {
208-
futures.remove(q.getId());
212+
futures.remove(sid);
209213
return q;
210214
}
211215
try {
212-
write(code, q.getId(), null, args);
216+
write(code, sid, null, args);
213217
} catch (Exception e) {
214-
futures.remove(q.getId());
218+
futures.remove(sid);
215219
fail(q, e);
216220
}
217221
return q;
@@ -225,11 +229,11 @@ protected synchronized void die(String message, Exception cause) {
225229
this.thumbstone = new CommunicationException(message, cause);
226230
this.alive = new CountDownLatch(1);
227231
while (!futures.isEmpty()) {
228-
Iterator<Map.Entry<Long, FutureImpl<List<?>>>> iterator = futures.entrySet().iterator();
232+
Iterator<Map.Entry<Long, CompletableFuture<List<?>>>> iterator = futures.entrySet().iterator();
229233
while (iterator.hasNext()) {
230-
Map.Entry<Long, FutureImpl<List<?>>> elem = iterator.next();
234+
Map.Entry<Long, CompletableFuture<List<?>>> elem = iterator.next();
231235
if (elem != null) {
232-
FutureImpl<List<?>> future = elem.getValue();
236+
CompletableFuture<List<?>> future = elem.getValue();
233237
fail(future, cause);
234238
}
235239
iterator.remove();
@@ -333,7 +337,7 @@ protected void readThread() {
333337
readPacket(is);
334338
code = (Long) headers.get(Key.CODE.getId());
335339
Long syncId = (Long) headers.get(Key.SYNC.getId());
336-
FutureImpl<List<?>> future = futures.remove(syncId);
340+
CompletableFuture<List<?>> future = futures.remove(syncId);
337341
stats.received++;
338342
wait.decrementAndGet();
339343
complete(code, future);
@@ -381,14 +385,14 @@ protected void writeThread() {
381385
}
382386

383387

384-
protected void fail(FutureImpl<List<?>> q, Exception e) {
385-
q.setError(e);
388+
protected void fail(CompletableFuture<List<?>> q, Exception e) {
389+
q.completeExceptionally(e);
386390
}
387391

388-
protected void complete(long code, FutureImpl<List<?>> q) {
392+
protected void complete(long code, CompletableFuture<List<?>> q) {
389393
if (q != null) {
390394
if (code == 0) {
391-
q.setValue((List) body.get(Key.DATA.getId()));
395+
q.complete((List) body.get(Key.DATA.getId()));
392396
} else {
393397
Object error = body.get(Key.ERROR.getId());
394398
fail(q, serverError(code, error));
@@ -488,6 +492,11 @@ public TarantoolClientOps<Integer, List<?>, Object, Future<List<?>>> asyncOps()
488492
return this;
489493
}
490494

495+
@Override
496+
public TarantoolClientOps<Integer, List<?>, Object, CompletionStage<List<?>>> composableAsyncOps() {
497+
return composableAsyncOps;
498+
}
499+
491500
@Override
492501
public TarantoolClientOps<Integer, List<?>, Object, Long> fireAndForgetOps() {
493502
return fireAndForgetOps;
@@ -529,7 +538,19 @@ public void close() {
529538
}
530539
}
531540

532-
protected boolean isDead(FutureImpl<List<?>> q) {
541+
protected class ComposableAsyncOps extends AbstractTarantoolOps<Integer, List<?>, Object, CompletionStage<List<?>>> {
542+
@Override
543+
public CompletionStage<List<?>> exec(Code code, Object... args) {
544+
return TarantoolClientImpl.this.exec(code, args);
545+
}
546+
547+
@Override
548+
public void close() {
549+
TarantoolClientImpl.this.close();
550+
}
551+
}
552+
553+
protected boolean isDead(CompletableFuture<List<?>> q) {
533554
if (TarantoolClientImpl.this.thumbstone != null) {
534555
fail(q, new CommunicationException("Connection is dead", thumbstone));
535556
return true;

0 commit comments

Comments
 (0)