Skip to content

Commit 8c34f54

Browse files
committed
Polishing
Rename ResponseReceiver to Conversation to reflect how the driver works internally. Add Javadoc to outline conversation semantics and to explain the test assertions. [pgjdbc#207][pgjdbc#230]
1 parent 25aa528 commit 8c34f54

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient.java

+16-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -102,7 +102,7 @@ public final class ReactorNettyClient implements Client {
102102

103103
private final FluxSink<Publisher<FrontendMessage>> requests = this.requestProcessor.sink();
104104

105-
private final Queue<ResponseReceiver> responseReceivers = Queues.<ResponseReceiver>unbounded().get();
105+
private final Queue<Conversation> conversations = Queues.<Conversation>unbounded().get();
106106

107107
private final DirectProcessor<NotificationResponse> notificationProcessor = DirectProcessor.create();
108108

@@ -139,11 +139,11 @@ private ReactorNettyClient(Connection connection) {
139139
handleConnectionError(throwable);
140140
})
141141
.handle((message, sink) -> {
142-
ResponseReceiver receiver = this.responseReceivers.peek();
142+
Conversation receiver = this.conversations.peek();
143143
if (receiver != null) {
144144
if (receiver.takeUntil.test(message)) {
145145
receiver.sink.complete();
146-
this.responseReceivers.poll();
146+
this.conversations.poll();
147147
} else {
148148
receiver.sink.next(message);
149149
}
@@ -174,6 +174,7 @@ private ReactorNettyClient(Connection connection) {
174174

175175
@Override
176176
public Flux<BackendMessage> exchange(Predicate<BackendMessage> takeUntil, Publisher<FrontendMessage> requests) {
177+
Assert.requireNonNull(takeUntil, "takeUntil must not be null");
177178
Assert.requireNonNull(requests, "requests must not be null");
178179

179180
return Flux
@@ -183,7 +184,7 @@ public Flux<BackendMessage> exchange(Predicate<BackendMessage> takeUntil, Publis
183184
return;
184185
}
185186
synchronized (this) {
186-
this.responseReceivers.add(new ResponseReceiver(sink, takeUntil));
187+
this.conversations.add(new Conversation(sink, takeUntil));
187188
this.requests.next(Flux.from(requests).doOnNext(m -> {
188189
if (!isConnected()) {
189190
sink.error(new PostgresConnectionClosedException("Cannot exchange messages because the connection is closed"));
@@ -379,9 +380,9 @@ public Mono<Void> close() {
379380
}
380381

381382
private void drainError(Supplier<? extends Throwable> supplier) {
382-
ResponseReceiver receiver;
383+
Conversation receiver;
383384

384-
while ((receiver = this.responseReceivers.poll()) != null) {
385+
while ((receiver = this.conversations.poll()) != null) {
385386
receiver.sink.error(supplier.get());
386387
}
387388
}
@@ -452,13 +453,19 @@ private void handleConnectionError(Throwable error) {
452453
drainError(() -> new PostgresConnectionException(error));
453454
}
454455

455-
private static class ResponseReceiver {
456+
/**
457+
* Value object representing a single conversation. The driver permits a single conversation at a time to ensure that request messages get routed to the proper response receiver and do not leak
458+
* into other conversations. A conversation must be finished in the sense that the {@link Publisher} of {@link FrontendMessage} has completed before the next conversation is started.
459+
* <p>
460+
* A single conversation can make use of pipelining.
461+
*/
462+
private static class Conversation {
456463

457464
private final FluxSink<BackendMessage> sink;
458465

459466
private final Predicate<BackendMessage> takeUntil;
460467

461-
private ResponseReceiver(FluxSink<BackendMessage> sink, Predicate<BackendMessage> takeUntil) {
468+
private Conversation(FluxSink<BackendMessage> sink, Predicate<BackendMessage> takeUntil) {
462469
this.sink = sink;
463470
this.takeUntil = takeUntil;
464471
}

src/test/java/io/r2dbc/postgresql/client/ReactorNettyClientIntegrationTests.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -311,10 +311,12 @@ void parallelExchangeExtendedFlow() {
311311
Describe describe2 = new Describe("P_2", ExecutionType.PORTAL);
312312
Execute execute2 = new Execute("P_2", Integer.MAX_VALUE);
313313

314-
315314
Flux<FrontendMessage> flow1 = Flux.just(bind1, describe1, execute1, Sync.INSTANCE).delayElements(Duration.ofMillis(10));
316315
Flux<FrontendMessage> flow2 = Flux.just(bind2, describe2, execute2, Sync.INSTANCE).delayElements(Duration.ofMillis(20));
317316

317+
// Actual response sequence is BindComplete/RowDescription/DataRow/CommandComplete for each of the extended flows
318+
// Zipping and flattening makes it appear in the assertions that it would be BindComplete/BindComplete/RowDescription/RowDescription…
319+
318320
this.datarowCleanup(Flux.zip(this.client.exchange(flow1), this.client.exchange(flow2))
319321
.flatMapIterable(t -> Arrays.asList(t.getT1(), t.getT2()))
320322
)

0 commit comments

Comments
 (0)