All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.rsocket.RSocketFactory Maven / Gradle / Ivy

There is a newer version: 1.1.5
Show newest version
/*
 * Copyright 2015-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.rsocket;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import io.rsocket.core.RSocketConnector;
import io.rsocket.core.RSocketServer;
import io.rsocket.core.Resume;
import io.rsocket.frame.decoder.PayloadDecoder;
import io.rsocket.lease.LeaseStats;
import io.rsocket.lease.Leases;
import io.rsocket.plugins.DuplexConnectionInterceptor;
import io.rsocket.plugins.RSocketInterceptor;
import io.rsocket.plugins.SocketAcceptorInterceptor;
import io.rsocket.resume.ClientResume;
import io.rsocket.resume.ResumableFramesStore;
import io.rsocket.resume.ResumeStrategy;
import io.rsocket.transport.ClientTransport;
import io.rsocket.transport.ServerTransport;
import java.time.Duration;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;

/**
 * Main entry point to create RSocket clients or servers as follows:
 *
 * 
    *
  • {@link ClientRSocketFactory} to connect as a client. Use {@link #connect()} for a default * instance. *
  • {@link ServerRSocketFactory} to start a server. Use {@link #receive()} for a default * instance. *
* * @deprecated please use {@link RSocketConnector} and {@link RSocketServer}. */ @Deprecated public final class RSocketFactory { /** * Create a {@code ClientRSocketFactory} to connect to a remote RSocket endpoint. Internally * delegates to {@link RSocketConnector}. * * @return the {@code ClientRSocketFactory} instance */ public static ClientRSocketFactory connect() { return new ClientRSocketFactory(); } /** * Create a {@code ServerRSocketFactory} to accept connections from RSocket clients. Internally * delegates to {@link RSocketServer}. * * @return the {@code ClientRSocketFactory} instance */ public static ServerRSocketFactory receive() { return new ServerRSocketFactory(); } public interface Start { Mono start(); } public interface ClientTransportAcceptor { Start transport(Supplier transport); default Start transport(ClientTransport transport) { return transport(() -> transport); } } public interface ServerTransportAcceptor { ServerTransport.ConnectionAcceptor toConnectionAcceptor(); Start transport(Supplier> transport); default Start transport(ServerTransport transport) { return transport(() -> transport); } } /** Factory to create and configure an RSocket client, and connect to a server. */ public static class ClientRSocketFactory implements ClientTransportAcceptor { private static final ClientResume CLIENT_RESUME = new ClientResume(Duration.ofMinutes(2), Unpooled.EMPTY_BUFFER); private final RSocketConnector connector; private Duration tickPeriod = Duration.ofSeconds(20); private Duration ackTimeout = Duration.ofSeconds(30); private int missedAcks = 3; private Resume resume; public ClientRSocketFactory() { this(RSocketConnector.create().errorConsumer(Throwable::printStackTrace)); } public ClientRSocketFactory(RSocketConnector connector) { this.connector = connector; } /** * @deprecated this method is deprecated and deliberately has no effect anymore. Right now, in * order configure the custom {@link ByteBufAllocator} it is recommended to use the * following setup for Reactor Netty based transport:
* 1. For Client:
*
{@code
     * TcpClient.create()
     *          ...
     *          .bootstrap(bootstrap -> bootstrap.option(ChannelOption.ALLOCATOR, clientAllocator))
     * }
*
* 2. For server:
*
{@code
     * TcpServer.create()
     *          ...
     *          .bootstrap(serverBootstrap -> serverBootstrap.childOption(ChannelOption.ALLOCATOR, serverAllocator))
     * }
* Or in case of local transport, to use corresponding factory method {@code * LocalClientTransport.creat(String, ByteBufAllocator)} * @param allocator instance of {@link ByteBufAllocator} * @return this factory instance */ public ClientRSocketFactory byteBufAllocator(ByteBufAllocator allocator) { return this; } public ClientRSocketFactory addConnectionPlugin(DuplexConnectionInterceptor interceptor) { connector.interceptors(registry -> registry.forConnection(interceptor)); return this; } /** Deprecated. Use {@link #addRequesterPlugin(RSocketInterceptor)} instead */ @Deprecated public ClientRSocketFactory addClientPlugin(RSocketInterceptor interceptor) { return addRequesterPlugin(interceptor); } public ClientRSocketFactory addRequesterPlugin(RSocketInterceptor interceptor) { connector.interceptors(registry -> registry.forRequester(interceptor)); return this; } /** Deprecated. Use {@link #addResponderPlugin(RSocketInterceptor)} instead */ @Deprecated public ClientRSocketFactory addServerPlugin(RSocketInterceptor interceptor) { return addResponderPlugin(interceptor); } public ClientRSocketFactory addResponderPlugin(RSocketInterceptor interceptor) { connector.interceptors(registry -> registry.forResponder(interceptor)); return this; } public ClientRSocketFactory addSocketAcceptorPlugin(SocketAcceptorInterceptor interceptor) { connector.interceptors(registry -> registry.forSocketAcceptor(interceptor)); return this; } /** * Deprecated without replacement as Keep-Alive is not optional according to spec * * @return this ClientRSocketFactory */ @Deprecated public ClientRSocketFactory keepAlive() { connector.keepAlive(tickPeriod, ackTimeout.plus(tickPeriod.multipliedBy(missedAcks))); return this; } public ClientTransportAcceptor keepAlive( Duration tickPeriod, Duration ackTimeout, int missedAcks) { this.tickPeriod = tickPeriod; this.ackTimeout = ackTimeout; this.missedAcks = missedAcks; keepAlive(); return this; } public ClientRSocketFactory keepAliveTickPeriod(Duration tickPeriod) { this.tickPeriod = tickPeriod; keepAlive(); return this; } public ClientRSocketFactory keepAliveAckTimeout(Duration ackTimeout) { this.ackTimeout = ackTimeout; keepAlive(); return this; } public ClientRSocketFactory keepAliveMissedAcks(int missedAcks) { this.missedAcks = missedAcks; keepAlive(); return this; } public ClientRSocketFactory mimeType(String metadataMimeType, String dataMimeType) { connector.metadataMimeType(metadataMimeType); connector.dataMimeType(dataMimeType); return this; } public ClientRSocketFactory dataMimeType(String dataMimeType) { connector.dataMimeType(dataMimeType); return this; } public ClientRSocketFactory metadataMimeType(String metadataMimeType) { connector.metadataMimeType(metadataMimeType); return this; } public ClientRSocketFactory lease(Supplier> supplier) { connector.lease(supplier); return this; } public ClientRSocketFactory lease() { connector.lease(Leases::new); return this; } /** @deprecated without a replacement and no longer used. */ @Deprecated public ClientRSocketFactory singleSubscriberRequester() { return this; } /** * Enables a reconnectable, shared instance of {@code Mono} so every subscriber will * observe the same RSocket instance up on connection establishment.
* For example: * *
{@code
     * Mono sharedRSocketMono =
     *   RSocketFactory
     *                .connect()
     *                .reconnect(Retry.fixedDelay(3, Duration.ofSeconds(1)))
     *                .transport(transport)
     *                .start();
     *
     *  RSocket r1 = sharedRSocketMono.block();
     *  RSocket r2 = sharedRSocketMono.block();
     *
     *  assert r1 == r2;
     *
     * }
* * Apart of the shared behavior, if the connection is lost, the same {@code Mono} * instance will transparently re-establish the connection for subsequent subscribers.
* For example: * *
{@code
     * Mono sharedRSocketMono =
     *   RSocketFactory
     *                .connect()
     *                .reconnect(Retry.fixedDelay(3, Duration.ofSeconds(1)))
     *                .transport(transport)
     *                .start();
     *
     *  RSocket r1 = sharedRSocketMono.block();
     *  RSocket r2 = sharedRSocketMono.block();
     *
     *  assert r1 == r2;
     *
     *  r1.dispose()
     *
     *  assert r2.isDisposed()
     *
     *  RSocket r3 = sharedRSocketMono.block();
     *  RSocket r4 = sharedRSocketMono.block();
     *
     *
     *  assert r1 != r3;
     *  assert r4 == r3;
     *
     * }
* * Note, having reconnect() enabled does not eliminate the need to accompany each * individual request with the corresponding retry logic.
* For example: * *
{@code
     * Mono sharedRSocketMono =
     *   RSocketFactory
     *                .connect()
     *                .reconnect(Retry.fixedDelay(3, Duration.ofSeconds(1)))
     *                .transport(transport)
     *                .start();
     *
     *  sharedRSocket.flatMap(rSocket -> rSocket.requestResponse(...))
     *               .retryWhen(ownRetry)
     *               .subscribe()
     *
     * }
* * @param retrySpec a retry factory applied for {@link Mono#retryWhen(Retry)} * @return a shared instance of {@code Mono}. */ public ClientRSocketFactory reconnect(Retry retrySpec) { connector.reconnect(retrySpec); return this; } public ClientRSocketFactory resume() { resume = resume != null ? resume : new Resume(); connector.resume(resume); return this; } public ClientRSocketFactory resumeToken(Supplier supplier) { resume(); resume.token(supplier); return this; } public ClientRSocketFactory resumeStore( Function storeFactory) { resume(); resume.storeFactory(storeFactory); return this; } public ClientRSocketFactory resumeSessionDuration(Duration sessionDuration) { resume(); resume.sessionDuration(sessionDuration); return this; } public ClientRSocketFactory resumeStreamTimeout(Duration streamTimeout) { resume(); resume.streamTimeout(streamTimeout); return this; } public ClientRSocketFactory resumeStrategy(Supplier strategy) { resume(); resume.retry( Retry.from( signals -> signals.flatMap(s -> strategy.get().apply(CLIENT_RESUME, s.failure())))); return this; } public ClientRSocketFactory resumeCleanupOnKeepAlive() { resume(); resume.cleanupStoreOnKeepAlive(); return this; } public Start transport(Supplier transport) { return () -> connector.connect(transport); } public ClientTransportAcceptor acceptor(Function acceptor) { return acceptor(() -> acceptor); } public ClientTransportAcceptor acceptor(Supplier> acceptorSupplier) { return acceptor( (setup, sendingSocket) -> { acceptorSupplier.get().apply(sendingSocket); return Mono.empty(); }); } public ClientTransportAcceptor acceptor(SocketAcceptor acceptor) { connector.acceptor(acceptor); return this; } public ClientRSocketFactory fragment(int mtu) { connector.fragment(mtu); return this; } /** @deprecated this is deprecated with no replacement. */ public ClientRSocketFactory errorConsumer(Consumer errorConsumer) { connector.errorConsumer(errorConsumer); return this; } public ClientRSocketFactory setupPayload(Payload payload) { connector.setupPayload(payload); return this; } public ClientRSocketFactory frameDecoder(PayloadDecoder payloadDecoder) { connector.payloadDecoder(payloadDecoder); return this; } } /** Factory to create, configure, and start an RSocket server. */ public static class ServerRSocketFactory implements ServerTransportAcceptor { private final RSocketServer server; private Resume resume; public ServerRSocketFactory() { this(RSocketServer.create().errorConsumer(Throwable::printStackTrace)); } public ServerRSocketFactory(RSocketServer server) { this.server = server; } /** * @deprecated this method is deprecated and deliberately has no effect anymore. Right now, in * order configure the custom {@link ByteBufAllocator} it is recommended to use the * following setup for Reactor Netty based transport:
* 1. For Client:
*
{@code
     * TcpClient.create()
     *          ...
     *          .bootstrap(bootstrap -> bootstrap.option(ChannelOption.ALLOCATOR, clientAllocator))
     * }
*
* 2. For server:
*
{@code
     * TcpServer.create()
     *          ...
     *          .bootstrap(serverBootstrap -> serverBootstrap.childOption(ChannelOption.ALLOCATOR, serverAllocator))
     * }
* Or in case of local transport, to use corresponding factory method {@code * LocalClientTransport.creat(String, ByteBufAllocator)} * @param allocator instance of {@link ByteBufAllocator} * @return this factory instance */ @Deprecated public ServerRSocketFactory byteBufAllocator(ByteBufAllocator allocator) { return this; } public ServerRSocketFactory addConnectionPlugin(DuplexConnectionInterceptor interceptor) { server.interceptors(registry -> registry.forConnection(interceptor)); return this; } /** Deprecated. Use {@link #addRequesterPlugin(RSocketInterceptor)} instead */ @Deprecated public ServerRSocketFactory addClientPlugin(RSocketInterceptor interceptor) { return addRequesterPlugin(interceptor); } public ServerRSocketFactory addRequesterPlugin(RSocketInterceptor interceptor) { server.interceptors(registry -> registry.forRequester(interceptor)); return this; } /** Deprecated. Use {@link #addResponderPlugin(RSocketInterceptor)} instead */ @Deprecated public ServerRSocketFactory addServerPlugin(RSocketInterceptor interceptor) { return addResponderPlugin(interceptor); } public ServerRSocketFactory addResponderPlugin(RSocketInterceptor interceptor) { server.interceptors(registry -> registry.forResponder(interceptor)); return this; } public ServerRSocketFactory addSocketAcceptorPlugin(SocketAcceptorInterceptor interceptor) { server.interceptors(registry -> registry.forSocketAcceptor(interceptor)); return this; } public ServerTransportAcceptor acceptor(SocketAcceptor acceptor) { server.acceptor(acceptor); return this; } public ServerRSocketFactory frameDecoder(PayloadDecoder payloadDecoder) { server.payloadDecoder(payloadDecoder); return this; } public ServerRSocketFactory fragment(int mtu) { server.fragment(mtu); return this; } /** @deprecated this is deprecated with no replacement. */ public ServerRSocketFactory errorConsumer(Consumer errorConsumer) { server.errorConsumer(errorConsumer); return this; } public ServerRSocketFactory lease(Supplier> supplier) { server.lease(supplier); return this; } public ServerRSocketFactory lease() { server.lease(Leases::new); return this; } /** @deprecated without a replacement and no longer used. */ @Deprecated public ServerRSocketFactory singleSubscriberRequester() { return this; } public ServerRSocketFactory resume() { resume = resume != null ? resume : new Resume(); server.resume(resume); return this; } public ServerRSocketFactory resumeStore( Function storeFactory) { resume(); resume.storeFactory(storeFactory); return this; } public ServerRSocketFactory resumeSessionDuration(Duration sessionDuration) { resume(); resume.sessionDuration(sessionDuration); return this; } public ServerRSocketFactory resumeStreamTimeout(Duration streamTimeout) { resume(); resume.streamTimeout(streamTimeout); return this; } public ServerRSocketFactory resumeCleanupOnKeepAlive() { resume(); resume.cleanupStoreOnKeepAlive(); return this; } @Override public ServerTransport.ConnectionAcceptor toConnectionAcceptor() { return server.asConnectionAcceptor(); } @Override public Start transport(Supplier> transport) { return () -> server.bind(transport.get()); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy