Skip to content

Commit ddaebb0

Browse files
committed
Basic stream implementation
1 parent b5cc841 commit ddaebb0

File tree

9 files changed

+285
-1
lines changed

9 files changed

+285
-1
lines changed

src/main/java/io/vertx/core/eventbus/EventBus.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import io.vertx.codegen.annotations.GenIgnore;
1616
import io.vertx.codegen.annotations.Nullable;
1717
import io.vertx.codegen.annotations.VertxGen;
18-
import io.vertx.core.AsyncResult;
1918
import io.vertx.core.Future;
2019
import io.vertx.core.Handler;
2120
import io.vertx.core.eventbus.impl.DefaultSerializableChecker;
@@ -199,6 +198,10 @@ default <T> Future<Message<T>> request(String address, @Nullable Object message)
199198
*/
200199
<T> MessageProducer<T> publisher(String address, DeliveryOptions options);
201200

201+
Future<Void> bindStream(String address, Handler<MessageStream> handler);
202+
203+
Future<MessageStream> connectStream(String address);
204+
202205
/**
203206
* Register a message codec.
204207
* <p>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) 2011-2021 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
package io.vertx.core.eventbus;
12+
13+
import io.vertx.codegen.annotations.VertxGen;
14+
import io.vertx.core.Handler;
15+
16+
@VertxGen
17+
public interface MessageStream {
18+
19+
void handler(Handler<Message<String>> handler);
20+
21+
void endHandler(Handler<Void> handler);
22+
23+
void write(String msg);
24+
25+
void end();
26+
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.vertx.core.eventbus.impl;
2+
3+
import io.vertx.core.Promise;
4+
import io.vertx.core.eventbus.MessageStream;
5+
import io.vertx.core.impl.ContextInternal;
6+
7+
class ClientStream extends StreamBase {
8+
9+
private final Promise<MessageStream> promise2;
10+
11+
public ClientStream(EventBusImpl eventBus, String sourceAddress, ContextInternal ctx, Promise<MessageStream> promise2) {
12+
super(sourceAddress, ctx, eventBus, sourceAddress, true);
13+
this.promise2 = promise2;
14+
}
15+
16+
@Override
17+
protected boolean doReceive(Frame frame) {
18+
if (frame instanceof SynFrame) {
19+
SynFrame syn = (SynFrame) frame;
20+
remoteAddress = syn.src;
21+
promise2.complete(this);
22+
return true;
23+
} else {
24+
return super.doReceive(frame);
25+
}
26+
}
27+
}

src/main/java/io/vertx/core/eventbus/impl/EventBusImpl.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,31 @@ public <T> MessageProducer<T> publisher(String address, DeliveryOptions options)
155155
return new MessageProducerImpl<>(vertx, address, false, options);
156156
}
157157

158+
@Override
159+
public Future<Void> bindStream(String address, Handler<MessageStream> handler) {
160+
ContextInternal ctx = vertx.getOrCreateContext();
161+
HandlerRegistration reg = new StreamServer(this, ctx, address, handler);
162+
Promise<Void> promise = ctx.promise();
163+
reg.register(true, false, promise);
164+
return promise.future();
165+
}
166+
167+
@Override
168+
public Future<MessageStream> connectStream(String address) {
169+
ContextInternal ctx = vertx.getOrCreateContext();
170+
String sourceAddress = generateReplyAddress();
171+
Promise<MessageStream> promise2 = ctx.promise();
172+
StreamBase reg = new ClientStream(this, sourceAddress, ctx, promise2);
173+
Promise<Void> promise = ctx.promise();
174+
reg.register(false, false, promise);
175+
promise.future().onComplete(ar -> {
176+
if (ar.succeeded()) {
177+
sendLocally(new SynFrame(sourceAddress, address), ctx.promise());
178+
}
179+
});
180+
return promise2.future();
181+
}
182+
158183
@Override
159184
public EventBus publish(String address, Object message) {
160185
return publish(address, message, new DeliveryOptions());
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.vertx.core.eventbus.impl;
2+
3+
import io.vertx.core.buffer.Buffer;
4+
5+
class FinFrame implements Frame {
6+
7+
final String addr;
8+
9+
public FinFrame(String addr) {
10+
this.addr = addr;
11+
}
12+
13+
@Override
14+
public String address() {
15+
return addr;
16+
}
17+
18+
@Override
19+
public Buffer encodeToWire() {
20+
throw new UnsupportedOperationException();
21+
}
22+
23+
@Override
24+
public boolean isFromWire() {
25+
return false;
26+
}
27+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package io.vertx.core.eventbus.impl;
2+
3+
import io.vertx.core.Handler;
4+
import io.vertx.core.MultiMap;
5+
import io.vertx.core.eventbus.Message;
6+
import io.vertx.core.eventbus.MessageStream;
7+
import io.vertx.core.impl.ContextInternal;
8+
9+
class StreamBase extends HandlerRegistration implements MessageStream {
10+
11+
private Handler<Message<String>> handler;
12+
private Handler<Void> endHandler;
13+
final String localAddress;
14+
String remoteAddress;
15+
private boolean halfClosed;
16+
17+
StreamBase(String localAddress, ContextInternal context, EventBusImpl bus, String address, boolean src) {
18+
super(context, bus, address, src);
19+
this.localAddress = localAddress;
20+
}
21+
22+
@Override
23+
protected boolean doReceive(Frame frame) {
24+
if (frame instanceof MessageImpl) {
25+
MessageImpl msg = (MessageImpl) frame;
26+
Handler<Message<String>> h = handler;
27+
if (h != null) {
28+
h.handle(msg);
29+
}
30+
} else if (frame instanceof FinFrame) {
31+
Handler<Void> h = endHandler;
32+
if (h != null) {
33+
h.handle(null);
34+
}
35+
if (halfClosed) {
36+
unregister();
37+
} else {
38+
halfClosed = true;
39+
}
40+
}
41+
return true;
42+
}
43+
44+
@Override
45+
protected void dispatch(Message msg, ContextInternal context, Handler handler) {
46+
47+
}
48+
49+
@Override
50+
public void handler(Handler<Message<String>> handler) {
51+
this.handler = handler;
52+
}
53+
54+
@Override
55+
public void endHandler(Handler<Void> handler) {
56+
this.endHandler = handler;
57+
}
58+
59+
@Override
60+
public void write(String body) {
61+
MessageImpl msg = new MessageImpl(remoteAddress, MultiMap.caseInsensitiveMultiMap(), body, CodecManager.STRING_MESSAGE_CODEC, true, bus);
62+
bus.sendLocally(msg, context.promise());
63+
}
64+
65+
@Override
66+
public void end() {
67+
FinFrame fin = new FinFrame(remoteAddress);
68+
bus.sendLocally(fin, context.promise());
69+
if (halfClosed) {
70+
unregister();
71+
} else {
72+
halfClosed = true;
73+
}
74+
}
75+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.vertx.core.eventbus.impl;
2+
3+
import io.vertx.core.Handler;
4+
import io.vertx.core.eventbus.Message;
5+
import io.vertx.core.eventbus.MessageStream;
6+
import io.vertx.core.impl.ContextInternal;
7+
import io.vertx.core.impl.future.PromiseInternal;
8+
9+
class StreamServer extends HandlerRegistration {
10+
private final EventBusImpl eventBus;
11+
private final Handler<MessageStream> handler;
12+
13+
public StreamServer(EventBusImpl eventBus, ContextInternal ctx, String address, Handler<MessageStream> handler) {
14+
super(ctx, eventBus, address, false);
15+
this.eventBus = eventBus;
16+
this.handler = handler;
17+
}
18+
19+
@Override
20+
protected boolean doReceive(Frame frame) {
21+
if (frame instanceof SynFrame) {
22+
SynFrame syn = (SynFrame) frame;
23+
String localAddress = eventBus.generateReplyAddress();
24+
StreamBase ss = new StreamBase(localAddress, context, eventBus, localAddress, false);
25+
ss.remoteAddress = syn.src;
26+
PromiseInternal<Void> p = context.promise();
27+
ss.register(false, true, p);
28+
p.onComplete(ar -> {
29+
if (ar.succeeded()) {
30+
SynFrame reply = new SynFrame(localAddress, syn.src);
31+
eventBus.sendLocally(reply, context.promise());
32+
handler.handle(ss);
33+
}
34+
});
35+
}
36+
return true;
37+
}
38+
39+
@Override
40+
protected void dispatch(Message msg, ContextInternal context, Handler handler) {
41+
}
42+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package io.vertx.core.eventbus.impl;
2+
3+
import io.vertx.core.buffer.Buffer;
4+
5+
public class SynFrame implements Frame {
6+
7+
final String src;
8+
final String dst;
9+
10+
public SynFrame(String src, String dst) {
11+
this.src = src;
12+
this.dst = dst;
13+
}
14+
15+
@Override
16+
public String address() {
17+
return dst;
18+
}
19+
20+
@Override
21+
public Buffer encodeToWire() {
22+
throw new UnsupportedOperationException();
23+
}
24+
25+
@Override
26+
public boolean isFromWire() {
27+
return false;
28+
}
29+
}

src/test/java/io/vertx/core/eventbus/LocalEventBusTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,5 +1531,34 @@ public void testEarlyTimeoutOnHandlerUnregistration() {
15311531
});
15321532
await();
15331533
}
1534+
1535+
@Test
1536+
public void testStream() throws Exception {
1537+
CountDownLatch latch = new CountDownLatch(1);
1538+
vertx.eventBus().bindStream(ADDRESS1, stream -> {
1539+
stream.handler(msg -> {
1540+
assertEquals("ping", msg.body());
1541+
stream.write(msg.body());
1542+
});
1543+
stream.endHandler(v -> {
1544+
stream.end();
1545+
});
1546+
}).onComplete(onSuccess(v -> {
1547+
latch.countDown();
1548+
}));
1549+
awaitLatch(latch);
1550+
vertx.eventBus().connectStream(ADDRESS1).onComplete(onSuccess(stream -> {
1551+
stream.write("ping");
1552+
stream.handler(msg -> {
1553+
assertEquals("ping", msg.body());
1554+
stream.end();
1555+
});
1556+
stream.endHandler(v -> {
1557+
testComplete();
1558+
});
1559+
}));
1560+
await();
1561+
}
1562+
15341563
}
15351564

0 commit comments

Comments
 (0)