|
44 | 44 | import java.util.function.BiConsumer;
|
45 | 45 | import java.util.function.Consumer;
|
46 | 46 | import java.util.function.Supplier;
|
| 47 | + |
47 | 48 | import reactor.core.Disposable;
|
48 | 49 | import reactor.core.publisher.Mono;
|
49 | 50 | import reactor.core.scheduler.Schedulers;
|
50 | 51 | import reactor.util.annotation.Nullable;
|
| 52 | +import reactor.util.function.Tuples; |
51 | 53 | import reactor.util.retry.Retry;
|
52 | 54 |
|
53 | 55 | /**
|
@@ -78,7 +80,7 @@ public class RSocketConnector {
|
78 | 80 | private static final BiConsumer<RSocket, Invalidatable> INVALIDATE_FUNCTION =
|
79 | 81 | (r, i) -> r.onClose().subscribe(null, __ -> i.invalidate(), i::invalidate);
|
80 | 82 |
|
81 |
| - private Payload setupPayload = EmptyPayload.INSTANCE; |
| 83 | + private Mono<Payload> setupPayloadMono = Mono.empty(); |
82 | 84 | private String metadataMimeType = "application/binary";
|
83 | 85 | private String dataMimeType = "application/binary";
|
84 | 86 | private Duration keepAliveInterval = Duration.ofSeconds(20);
|
@@ -128,22 +130,38 @@ public static RSocketClient createRSocketClient(ClientTransport transport) {
|
128 | 130 | }
|
129 | 131 |
|
130 | 132 | /**
|
131 |
| - * Provide a {@code Payload} with data and/or metadata for the initial {@code SETUP} frame. Data |
132 |
| - * and metadata should be formatted according to the MIME types specified via {@link |
| 133 | + * Provide a {@code Mono} from which to obtain the {@code Payload} for the initial SETUP frame. |
| 134 | + * Data and metadata should be formatted according to the MIME types specified via {@link |
133 | 135 | * #dataMimeType(String)} and {@link #metadataMimeType(String)}.
|
134 | 136 | *
|
135 |
| - * @param payload the payload containing data and/or metadata for the {@code SETUP} frame. Note, |
136 |
| - * if the instance of the given payload is not a {@link DefaultPayload}, its content will be |
137 |
| - * copied |
| 137 | + * @param setupPayloadMono the payload with data and/or metadata for the {@code SETUP} frame. |
| 138 | + * @return the same instance for method chaining |
| 139 | + * @since 1.0.2 |
| 140 | + * @see <a href="https://github.com/rsocket/rsocket/blob/master/Protocol.md#frame-setup">SETUP |
| 141 | + * Frame</a> |
| 142 | + */ |
| 143 | + public RSocketConnector setupPayload(Mono<Payload> setupPayloadMono) { |
| 144 | + this.setupPayloadMono = setupPayloadMono; |
| 145 | + return this; |
| 146 | + } |
| 147 | + |
| 148 | + /** |
| 149 | + * Variant of {@link #setupPayload(Mono)} that accepts a {@code Payload} instance. |
| 150 | + * |
| 151 | + * <p>Note: if the given payload is {@link io.rsocket.util.ByteBufPayload}, it is copied to a |
| 152 | + * {@link DefaultPayload} and released immediately. This ensures it can re-used to obtain a |
| 153 | + * connection more than once. |
| 154 | + * |
| 155 | + * @param payload the payload with data and/or metadata for the {@code SETUP} frame. |
138 | 156 | * @return the same instance for method chaining
|
139 | 157 | * @see <a href="https://github.com/rsocket/rsocket/blob/master/Protocol.md#frame-setup">SETUP
|
140 | 158 | * Frame</a>
|
141 | 159 | */
|
142 | 160 | public RSocketConnector setupPayload(Payload payload) {
|
143 | 161 | if (payload instanceof DefaultPayload) {
|
144 |
| - this.setupPayload = payload; |
| 162 | + this.setupPayloadMono = Mono.just(payload); |
145 | 163 | } else {
|
146 |
| - this.setupPayload = DefaultPayload.create(Objects.requireNonNull(payload)); |
| 164 | + this.setupPayloadMono = Mono.just(DefaultPayload.create(Objects.requireNonNull(payload))); |
147 | 165 | payload.release();
|
148 | 166 | }
|
149 | 167 | return this;
|
@@ -532,8 +550,19 @@ private Mono<RSocket> connect0(Supplier<ClientTransport> transportSupplier) {
|
532 | 550 | mtu > 0
|
533 | 551 | ? new FragmentationDuplexConnection(connection, mtu, "client")
|
534 | 552 | : new ReassemblyDuplexConnection(connection));
|
535 |
| - return connectionMono.flatMap( |
536 |
| - connection -> { |
| 553 | + return connectionMono |
| 554 | + .flatMap( |
| 555 | + connection -> |
| 556 | + setupPayloadMono |
| 557 | + .defaultIfEmpty(EmptyPayload.INSTANCE) |
| 558 | + .map(setupPayload -> Tuples.of(connection, setupPayload)) |
| 559 | + .doOnError(ex -> connection.dispose()) |
| 560 | + .doOnCancel(connection::dispose)) |
| 561 | + .flatMap( |
| 562 | + tuple -> { |
| 563 | + DuplexConnection connection = tuple.getT1(); |
| 564 | + Payload setupPayload = tuple.getT2(); |
| 565 | + |
537 | 566 | ByteBuf resumeToken;
|
538 | 567 | KeepAliveHandler keepAliveHandler;
|
539 | 568 | DuplexConnection wrappedConnection;
|
|
0 commit comments