From a3c68d7d3b3141c88808ebe237272142bce31ff7 Mon Sep 17 00:00:00 2001 From: Artem Vysochyn Date: Tue, 8 Oct 2024 22:56:40 +0300 Subject: [PATCH] Better bootstrap process (#854) --- .github/workflows/branch-ci.yml | 17 +- .github/workflows/pre-release-ci.yml | 15 +- .github/workflows/release-ci.yml | 24 +- pom.xml | 20 +- .../discovery/api/ServiceDiscovery.java | 11 +- .../api/ServiceDiscoveryOptions.java | 49 - .../scalecube/services/gateway/Gateway.java | 15 +- .../registry/api/ServiceRegistry.java | 4 +- .../transport/api/ServerTransport.java | 4 +- services-discovery/pom.xml | 3 - .../discovery/ScalecubeServiceDiscovery.java | 17 +- services-examples/pom.xml | 9 +- .../auth/CompositeProfileAuthExample.java | 41 +- .../auth/PrincipalMapperAuthExample.java | 55 +- .../auth/ServiceTransportAuthExample.java | 30 +- .../services/examples/codecs/Example1.java | 44 +- .../exceptions/ExceptionMapperExample.java | 66 +- .../examples/gateway/HttpGatewayExample.java | 51 - .../gateway/WebsocketGatewayExample.java | 51 - .../examples/helloworld/Example1.java | 41 +- .../examples/helloworld/Example2.java | 40 +- .../examples/helloworld/Example3.java | 41 +- .../services/examples/services/Example1.java | 63 +- .../services/examples/services/Example2.java | 63 +- services-gateway/pom.xml | 10 +- .../gateway/GatewaySessionHandler.java | 25 +- .../services/gateway/ReferenceCountUtil.java | 12 +- .../http/HttpGatewayClientTransport.java | 10 +- .../WebsocketGatewayClientSession.java | 28 +- .../WebsocketGatewayClientTransport.java | 22 +- .../services/gateway/http/HttpGateway.java | 62 +- .../gateway/http/HttpGatewayAcceptor.java | 13 +- .../gateway/websocket/WebsocketGateway.java | 64 +- .../websocket/WebsocketGatewaySession.java | 26 +- .../gateway/GatewaySessionHandlerImpl.java | 5 +- .../services/gateway/http/CorsTest.java | 38 +- .../http/HttpClientConnectionTest.java | 49 +- .../gateway/http/HttpGatewayTest.java | 59 +- .../gateway/http/HttpLocalGatewayTest.java | 17 +- .../WebsocketClientConnectionTest.java | 59 +- .../websocket/WebsocketClientTest.java | 67 +- .../websocket/WebsocketGatewayAuthTest.java | 19 +- .../websocket/WebsocketGatewayTest.java | 50 +- .../websocket/WebsocketLocalGatewayTest.java | 27 +- .../websocket/WebsocketServerTest.java | 20 +- .../security/ServiceTokenAuthenticator.java | 10 +- .../services-transport-rsocket/pom.xml | 6 - .../rsocket/RSocketServiceTransport.java | 18 +- services/pom.xml | 8 +- .../java/io/scalecube/services/Injector.java | 2 +- .../io/scalecube/services/Microservices.java | 915 +++++++++--------- .../registry/ServiceRegistryImpl.java | 12 +- .../io/scalecube/services/ErrorFlowTest.java | 46 +- .../services/ServiceAuthRemoteTest.java | 115 +-- .../services/ServiceCallLocalTest.java | 23 +- .../services/ServiceCallRemoteTest.java | 45 +- .../ServiceDiscoverySubscriberTest.java | 7 +- .../ServiceLifecycleAnnotationsTest.java | 77 +- .../scalecube/services/ServiceLocalTest.java | 11 +- .../services/ServiceRegistryTest.java | 112 ++- .../scalecube/services/ServiceRemoteTest.java | 107 +- .../services/StreamingServiceTest.java | 51 +- .../services/routings/RoutersTest.java | 130 ++- .../services/routings/ServiceTagsExample.java | 69 +- .../services/sut/SimpleQuoteService.java | 4 +- ...ocketNettyColocatedEventLoopGroupTest.java | 89 +- .../rsocket/RSocketServiceTransportTest.java | 60 +- 67 files changed, 1599 insertions(+), 1774 deletions(-) delete mode 100644 services-api/src/main/java/io/scalecube/services/discovery/api/ServiceDiscoveryOptions.java delete mode 100644 services-examples/src/main/java/io/scalecube/services/examples/gateway/HttpGatewayExample.java delete mode 100644 services-examples/src/main/java/io/scalecube/services/examples/gateway/WebsocketGatewayExample.java diff --git a/.github/workflows/branch-ci.yml b/.github/workflows/branch-ci.yml index 603791e5a..5787348a7 100644 --- a/.github/workflows/branch-ci.yml +++ b/.github/workflows/branch-ci.yml @@ -14,25 +14,24 @@ jobs: name: Branch CI runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/cache@v1 + - uses: actions/checkout@v4 + - uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - name: Set up JDK + uses: actions/setup-java@v4 with: - java-version: 1.8 + java-version: 17 + distribution: zulu server-id: github server-username: GITHUB_ACTOR server-password: GITHUB_TOKEN - name: Maven Build - run: mvn clean install -DskipTests=true -Dmaven.javadoc.skip=true -Ddockerfile.skip=true -B -V + run: mvn clean install -DskipTests=true -Dmaven.javadoc.skip=true -B -V env: GITHUB_TOKEN: ${{ secrets.ORGANIZATION_TOKEN }} - name: Maven Verify - run: | - sudo echo "127.0.0.1 $(eval hostname)" | sudo tee -a /etc/hosts - mvn verify -B + run: mvn verify -B diff --git a/.github/workflows/pre-release-ci.yml b/.github/workflows/pre-release-ci.yml index 4948f5bc2..245e4d483 100644 --- a/.github/workflows/pre-release-ci.yml +++ b/.github/workflows/pre-release-ci.yml @@ -9,23 +9,23 @@ jobs: name: Pre-release CI runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/cache@v1 + - uses: actions/checkout@v4 + - uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up Java for publishing to GitHub Packages - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: 1.8 + java-version: 17 + distribution: zulu server-id: github server-username: GITHUB_ACTOR server-password: GITHUB_TOKEN - name: Deploy pre-release version to GitHub Packages run: | - sudo echo "127.0.0.1 $(eval hostname)" | sudo tee -a /etc/hosts pre_release_version=${{ github.event.release.tag_name }} echo Pre-release version $pre_release_version mvn versions:set -DnewVersion=$pre_release_version -DgenerateBackupPoms=false @@ -34,9 +34,10 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.ORGANIZATION_TOKEN }} - name: Set up Java for publishing to Maven Central Repository - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: 1.8 + java-version: 17 + distribution: zulu server-id: ossrh server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 32e3623ac..4924f5266 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -9,31 +9,30 @@ jobs: name: Release CI runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - run: git checkout ${{ github.event.release.target_commitish }} - - uses: actions/cache@v1 + - uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up Java for publishing to GitHub Packages - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: 1.8 + java-version: 17 + distribution: zulu server-id: github server-username: GITHUB_ACTOR server-password: GITHUB_TOKEN - name: Maven Build - run: mvn clean install -DskipTests=true -Ddockerfile.skip=true -B -V + run: mvn clean install -DskipTests=true -B -V env: GITHUB_TOKEN: ${{ secrets.ORGANIZATION_TOKEN }} - name: Maven Verify - run: | - sudo echo "127.0.0.1 $(eval hostname)" | sudo tee -a /etc/hosts - mvn verify -B + run: mvn verify -B - name: Configure git run: | git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" @@ -43,17 +42,18 @@ jobs: run: | mvn -B build-helper:parse-version release:prepare \ -DreleaseVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.incrementalVersion} \ - -Darguments="-DskipTests=true -Ddockerfile.skip=true" + -Darguments="-DskipTests=true" echo release_tag=$(git describe --tags --abbrev=0) >> $GITHUB_OUTPUT - name: Perform release - run: mvn -B release:perform -Pdeploy2Github -Darguments="-DskipTests=true -Ddockerfile.skip=true -Pdeploy2Github" + run: mvn -B release:perform -Pdeploy2Github -Darguments="-DskipTests=true -Pdeploy2Github" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_REPOSITORY: ${{ secrets.GITHUB_REPOSITORY }} - name: Set up Java for publishing to Maven Central Repository - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: 1.8 + java-version: 17 + distribution: zulu server-id: ossrh server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD diff --git a/pom.xml b/pom.xml index d09049960..94c61f3f5 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ io.scalecube scalecube-parent - 0.2.20 + 0.3.1 scalecube-services-parent @@ -59,23 +59,22 @@ - 2.6.18.rc1 - 1.0.32 + 2.6.18.RC10 + 1.0.33.RC1 2020.0.32 - 2.15.1 + 2.18.0 4.1.93.Final 1.1.4 1.6.0 - 1.7.36 - 2.17.2 - 3.4.2 3.0.2 2.1.2 4.6.1 5.8.2 1.3 + 2.17.2 + 1.7.36 https://maven.pkg.github.com/scalecube/scalecube-services @@ -150,13 +149,6 @@ import - - - com.lmax - disruptor - ${disruptor.version} - - io.rsocket diff --git a/services-api/src/main/java/io/scalecube/services/discovery/api/ServiceDiscovery.java b/services-api/src/main/java/io/scalecube/services/discovery/api/ServiceDiscovery.java index a1b804c11..88f035b03 100644 --- a/services-api/src/main/java/io/scalecube/services/discovery/api/ServiceDiscovery.java +++ b/services-api/src/main/java/io/scalecube/services/discovery/api/ServiceDiscovery.java @@ -13,18 +13,15 @@ public interface ServiceDiscovery { Address address(); /** - * Function to subscribe and listen on stream of {@code ServiceDiscoveryEvent}\s. + * Function to subscribe and listen on service discovery stream. * - * @return stream of {@code ServiceDiscoveryEvent}\s + * @return stream of {@code ServiceDiscoveryEvent} objects */ Flux listen(); - /** - * Starts this {@link ServiceDiscovery} instance. After started - subscribers begin to receive - * {@code ServiceDiscoveryEvent}\s on {@link #listen()}. - */ + /** Starts this instance. */ void start(); - /** Stops this {@link ServiceDiscovery} instance and release occupied resources. */ + /** Stops this instance and release occupied resources. */ void shutdown(); } diff --git a/services-api/src/main/java/io/scalecube/services/discovery/api/ServiceDiscoveryOptions.java b/services-api/src/main/java/io/scalecube/services/discovery/api/ServiceDiscoveryOptions.java deleted file mode 100644 index f095a5087..000000000 --- a/services-api/src/main/java/io/scalecube/services/discovery/api/ServiceDiscoveryOptions.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.scalecube.services.discovery.api; - -import io.scalecube.services.ServiceEndpoint; -import java.util.StringJoiner; - -public final class ServiceDiscoveryOptions implements Cloneable { - - private ServiceEndpoint serviceEndpoint; - private ServiceDiscoveryFactory discoveryFactory; - - public ServiceDiscoveryOptions() {} - - public ServiceEndpoint serviceEndpoint() { - return serviceEndpoint; - } - - public ServiceDiscoveryOptions serviceEndpoint(ServiceEndpoint serviceEndpoint) { - final ServiceDiscoveryOptions c = clone(); - c.serviceEndpoint = serviceEndpoint; - return c; - } - - public ServiceDiscoveryFactory discoveryFactory() { - return discoveryFactory; - } - - public ServiceDiscoveryOptions discoveryFactory(ServiceDiscoveryFactory discoveryFactory) { - final ServiceDiscoveryOptions c = clone(); - c.discoveryFactory = discoveryFactory; - return c; - } - - @Override - public ServiceDiscoveryOptions clone() { - try { - return (ServiceDiscoveryOptions) super.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - - @Override - public String toString() { - return new StringJoiner(", ", ServiceDiscoveryOptions.class.getSimpleName() + "[", "]") - .add("serviceEndpoint=" + serviceEndpoint) - .add("discoveryFactory=" + discoveryFactory) - .toString(); - } -} diff --git a/services-api/src/main/java/io/scalecube/services/gateway/Gateway.java b/services-api/src/main/java/io/scalecube/services/gateway/Gateway.java index cc0ed2d29..5cc4d5a5b 100644 --- a/services-api/src/main/java/io/scalecube/services/gateway/Gateway.java +++ b/services-api/src/main/java/io/scalecube/services/gateway/Gateway.java @@ -1,7 +1,6 @@ package io.scalecube.services.gateway; import io.scalecube.services.Address; -import reactor.core.publisher.Mono; public interface Gateway { @@ -20,16 +19,12 @@ public interface Gateway { Address address(); /** - * Starts the gateway. + * Starts gateway. * - * @return mono result + * @return gateway instance */ - Mono start(); + Gateway start(); - /** - * Stops the gateway. - * - * @return stop signal - */ - Mono stop(); + /** Stops gateway. */ + void stop(); } diff --git a/services-api/src/main/java/io/scalecube/services/registry/api/ServiceRegistry.java b/services-api/src/main/java/io/scalecube/services/registry/api/ServiceRegistry.java index 49b0be33f..5c3afcd2f 100644 --- a/services-api/src/main/java/io/scalecube/services/registry/api/ServiceRegistry.java +++ b/services-api/src/main/java/io/scalecube/services/registry/api/ServiceRegistry.java @@ -21,10 +21,10 @@ public interface ServiceRegistry { boolean registerService(ServiceEndpoint serviceEndpoint); - ServiceEndpoint unregisterService(String endpointId); - void registerService(ServiceInfo serviceInfo); + ServiceEndpoint unregisterService(String endpointId); + List listServices(); ServiceMethodInvoker getInvoker(String qualifier); diff --git a/services-api/src/main/java/io/scalecube/services/transport/api/ServerTransport.java b/services-api/src/main/java/io/scalecube/services/transport/api/ServerTransport.java index 26a9a79ca..16f4c88bc 100644 --- a/services-api/src/main/java/io/scalecube/services/transport/api/ServerTransport.java +++ b/services-api/src/main/java/io/scalecube/services/transport/api/ServerTransport.java @@ -12,12 +12,12 @@ public interface ServerTransport { Address address(); /** - * Starts {@link ServiceTransport} instance. + * Starts this instance. * * @return transport instance */ ServerTransport bind(); - /** Stops this {@link ServiceTransport} instance and release occupied resources. */ + /** Stops this instance and release occupied resources. */ void stop(); } diff --git a/services-discovery/pom.xml b/services-discovery/pom.xml index 21c370316..3a4e9e69f 100644 --- a/services-discovery/pom.xml +++ b/services-discovery/pom.xml @@ -14,13 +14,11 @@ io.scalecube scalecube-cluster - io.scalecube scalecube-services-api ${project.version} - org.apache.logging.log4j @@ -32,7 +30,6 @@ log4j-core test - io.scalecube scalecube-codec-jackson diff --git a/services-discovery/src/main/java/io/scalecube/services/discovery/ScalecubeServiceDiscovery.java b/services-discovery/src/main/java/io/scalecube/services/discovery/ScalecubeServiceDiscovery.java index 4874b99ec..cb482b259 100644 --- a/services-discovery/src/main/java/io/scalecube/services/discovery/ScalecubeServiceDiscovery.java +++ b/services-discovery/src/main/java/io/scalecube/services/discovery/ScalecubeServiceDiscovery.java @@ -18,19 +18,19 @@ import io.scalecube.services.ServiceEndpoint; import io.scalecube.services.discovery.api.ServiceDiscovery; import io.scalecube.services.discovery.api.ServiceDiscoveryEvent; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.nio.ByteBuffer; import java.time.Duration; import java.util.StringJoiner; import java.util.function.UnaryOperator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.Exceptions; import reactor.core.publisher.Flux; import reactor.core.publisher.Sinks; public final class ScalecubeServiceDiscovery implements ServiceDiscovery { - private static final Logger LOGGER = LoggerFactory.getLogger(ServiceDiscovery.class); + private static final Logger LOGGER = System.getLogger(ServiceDiscovery.class.getName()); private ClusterConfig clusterConfig; private Cluster cluster; @@ -107,17 +107,18 @@ public void shutdown() { } private void onMembershipEvent(MembershipEvent membershipEvent) { - LOGGER.debug("onMembershipEvent: {}", membershipEvent); + LOGGER.log(Level.DEBUG, "onMembershipEvent: {0}", membershipEvent); ServiceDiscoveryEvent discoveryEvent = toServiceDiscoveryEvent(membershipEvent); if (discoveryEvent == null) { - LOGGER.warn( - "DiscoveryEvent is null, cannot publish it (corresponding membershipEvent: {})", + LOGGER.log( + Level.WARNING, + "DiscoveryEvent is null, cannot publish it (corresponding membershipEvent: {0})", membershipEvent); return; } - LOGGER.debug("Publish discoveryEvent: {}", discoveryEvent); + LOGGER.log(Level.DEBUG, "Publish discoveryEvent: {0}", discoveryEvent); sink.emitNext(discoveryEvent, busyLooping(Duration.ofSeconds(3))); } @@ -141,7 +142,7 @@ private ServiceEndpoint toServiceEndpoint(ByteBuffer byteBuffer) { try { return (ServiceEndpoint) clusterConfig.metadataCodec().deserialize(byteBuffer.duplicate()); } catch (Exception e) { - LOGGER.error("Failed to read metadata", e); + LOGGER.log(Level.ERROR, "Failed to read metadata", e); throw Exceptions.propagate(e); } } diff --git a/services-examples/pom.xml b/services-examples/pom.xml index b924d66ee..5c590bef1 100644 --- a/services-examples/pom.xml +++ b/services-examples/pom.xml @@ -49,18 +49,17 @@ fastutil 8.1.1 - - org.slf4j - slf4j-api + org.apache.logging.log4j + log4j-core org.apache.logging.log4j - log4j-slf4j-impl + log4j-jpl org.apache.logging.log4j - log4j-core + log4j-slf4j-impl diff --git a/services-examples/src/main/java/io/scalecube/services/examples/auth/CompositeProfileAuthExample.java b/services-examples/src/main/java/io/scalecube/services/examples/auth/CompositeProfileAuthExample.java index b67d63fee..95d3f39d0 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/auth/CompositeProfileAuthExample.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/auth/CompositeProfileAuthExample.java @@ -3,6 +3,7 @@ import static io.scalecube.services.auth.Authenticator.deferSecured; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceEndpoint; import io.scalecube.services.ServiceInfo; import io.scalecube.services.api.ServiceMessage; @@ -25,27 +26,29 @@ public class CompositeProfileAuthExample { */ public static void main(String[] args) { Microservices service = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(() -> new RSocketServiceTransport().authenticator(authenticator())) - .services( - call -> - Collections.singletonList( - ServiceInfo.fromServiceInstance(new SecuredServiceByCompositeProfileImpl()) - .authenticator(compositeAuthenticator()) - .build())) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(() -> new RSocketServiceTransport().authenticator(authenticator())) + .services( + call -> + Collections.singletonList( + ServiceInfo.fromServiceInstance( + new SecuredServiceByCompositeProfileImpl()) + .authenticator(compositeAuthenticator()) + .build()))); Microservices caller = - Microservices.builder() - .discovery(endpoint -> discovery(service, endpoint)) - .transport( - () -> new RSocketServiceTransport().credentialsSupplier(credentialsSupplier())) - .startAwait(); + Microservices.start( + new Context() + .discovery(endpoint -> discovery(service, endpoint)) + .transport( + () -> + new RSocketServiceTransport().credentialsSupplier(credentialsSupplier()))); ServiceMessage response = caller diff --git a/services-examples/src/main/java/io/scalecube/services/examples/auth/PrincipalMapperAuthExample.java b/services-examples/src/main/java/io/scalecube/services/examples/auth/PrincipalMapperAuthExample.java index abbf515c9..923ed3134 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/auth/PrincipalMapperAuthExample.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/auth/PrincipalMapperAuthExample.java @@ -1,6 +1,7 @@ package io.scalecube.services.examples.auth; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceEndpoint; import io.scalecube.services.ServiceInfo; import io.scalecube.services.auth.Authenticator; @@ -24,29 +25,30 @@ public class PrincipalMapperAuthExample { */ public static void main(String[] args) { Microservices service = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(() -> new RSocketServiceTransport().authenticator(authenticator())) - .services( - ServiceInfo.fromServiceInstance(new SecuredServiceByApiKeyImpl()) - .principalMapper(PrincipalMapperAuthExample::apiKeyPrincipalMapper) - .build()) - .services( - ServiceInfo.fromServiceInstance(new SecuredServiceByUserProfileImpl()) - .principalMapper(PrincipalMapperAuthExample::userProfilePrincipalMapper) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(() -> new RSocketServiceTransport().authenticator(authenticator())) + .services( + ServiceInfo.fromServiceInstance(new SecuredServiceByApiKeyImpl()) + .principalMapper(PrincipalMapperAuthExample::apiKeyPrincipalMapper) + .build()) + .services( + ServiceInfo.fromServiceInstance(new SecuredServiceByUserProfileImpl()) + .principalMapper(PrincipalMapperAuthExample::userProfilePrincipalMapper) + .build())); Microservices userProfileCaller = - Microservices.builder() - .discovery(endpoint -> discovery(service, endpoint)) - .transport( - () -> new RSocketServiceTransport().credentialsSupplier(credentialsSupplier())) - .startAwait(); + Microservices.start( + new Context() + .discovery(endpoint -> discovery(service, endpoint)) + .transport( + () -> + new RSocketServiceTransport().credentialsSupplier(credentialsSupplier()))); String responseByUserProfile = userProfileCaller @@ -58,11 +60,12 @@ public static void main(String[] args) { System.err.println("### Received 'userProfileCaller' response: " + responseByUserProfile); Microservices apiKeyCaller = - Microservices.builder() - .discovery(endpoint -> discovery(service, endpoint)) - .transport( - () -> new RSocketServiceTransport().credentialsSupplier(credentialsSupplier())) - .startAwait(); + Microservices.start( + new Context() + .discovery(endpoint -> discovery(service, endpoint)) + .transport( + () -> + new RSocketServiceTransport().credentialsSupplier(credentialsSupplier()))); String responseByApiKey = apiKeyCaller diff --git a/services-examples/src/main/java/io/scalecube/services/examples/auth/ServiceTransportAuthExample.java b/services-examples/src/main/java/io/scalecube/services/examples/auth/ServiceTransportAuthExample.java index 52ea9b101..ec057f03c 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/auth/ServiceTransportAuthExample.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/auth/ServiceTransportAuthExample.java @@ -1,6 +1,7 @@ package io.scalecube.services.examples.auth; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceEndpoint; import io.scalecube.services.auth.Authenticator; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; @@ -22,22 +23,23 @@ public class ServiceTransportAuthExample { */ public static void main(String[] args) { Microservices service = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(() -> new RSocketServiceTransport().authenticator(authenticator())) - .services(new SecuredServiceByUserProfileImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(() -> new RSocketServiceTransport().authenticator(authenticator())) + .services(new SecuredServiceByUserProfileImpl())); Microservices caller = - Microservices.builder() - .discovery(endpoint -> discovery(service, endpoint)) - .transport( - () -> new RSocketServiceTransport().credentialsSupplier(credentialsSupplier())) - .startAwait(); + Microservices.start( + new Context() + .discovery(endpoint -> discovery(service, endpoint)) + .transport( + () -> + new RSocketServiceTransport().credentialsSupplier(credentialsSupplier()))); String response = caller diff --git a/services-examples/src/main/java/io/scalecube/services/examples/codecs/Example1.java b/services-examples/src/main/java/io/scalecube/services/examples/codecs/Example1.java index 0c03f973a..48867d4db 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/codecs/Example1.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/codecs/Example1.java @@ -2,6 +2,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.examples.helloworld.service.GreetingServiceImpl; import io.scalecube.services.examples.helloworld.service.api.GreetingsService; @@ -22,30 +23,31 @@ public class Example1 { public static void main(String[] args) { // ScaleCube Node with no members Microservices seed = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .defaultContentType(PROTOSTUFF) // set explicit default data format - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + // .defaultContentType(PROTOSTUFF) // set explicit default data format + ); final Address seedAddress = seed.discoveryAddress(); // Construct a ScaleCube node which joins the cluster hosting the Greeting Service Microservices ms = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); seed.call() .api(GreetingsService.class) @@ -64,7 +66,7 @@ public static void main(String[] args) { .sayHello("bob (on java native Serializable/Externalizable dataFormat)") .subscribe(consumer -> System.out.println(consumer.message())); - seed.onShutdown().block(); - ms.onShutdown().block(); + seed.close(); + ms.close(); } } diff --git a/services-examples/src/main/java/io/scalecube/services/examples/exceptions/ExceptionMapperExample.java b/services-examples/src/main/java/io/scalecube/services/examples/exceptions/ExceptionMapperExample.java index 37f03aeb1..f8912c453 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/exceptions/ExceptionMapperExample.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/exceptions/ExceptionMapperExample.java @@ -2,6 +2,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceInfo; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.transport.rsocket.RSocketServiceTransport; @@ -18,45 +19,48 @@ public class ExceptionMapperExample { */ public static void main(String[] args) throws InterruptedException { Microservices ms1 = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .defaultErrorMapper(new ServiceAProviderErrorMapper()) // default mapper for whole node - .services( - ServiceInfo.fromServiceInstance(new ServiceAImpl()) - .errorMapper(new ServiceAProviderErrorMapper()) // mapper per service instance - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .defaultErrorMapper( + new ServiceAProviderErrorMapper()) // default mapper for whole node + .services( + ServiceInfo.fromServiceInstance(new ServiceAImpl()) + .errorMapper( + new ServiceAProviderErrorMapper()) // mapper per service instance + .build())); System.err.println("ms1 started: " + ms1.serviceAddress()); final Address address1 = ms1.discoveryAddress(); Microservices ms2 = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(address1.toString()))) - .transport(RSocketServiceTransport::new) - .services( - call -> { - ServiceA serviceA = - call.errorMapper( - new ServiceAClientErrorMapper()) // service client error mapper - .api(ServiceA.class); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(address1.toString()))) + .transport(RSocketServiceTransport::new) + .services( + call -> { + ServiceA serviceA = + call.errorMapper( + new ServiceAClientErrorMapper()) // service client error mapper + .api(ServiceA.class); - ServiceB serviceB = new ServiceBImpl(serviceA); + ServiceB serviceB = new ServiceBImpl(serviceA); - return Collections.singleton(ServiceInfo.fromServiceInstance(serviceB).build()); - }) - .startAwait(); + return Collections.singleton( + ServiceInfo.fromServiceInstance(serviceB).build()); + })); System.err.println("ms2 started: " + ms2.serviceAddress()); diff --git a/services-examples/src/main/java/io/scalecube/services/examples/gateway/HttpGatewayExample.java b/services-examples/src/main/java/io/scalecube/services/examples/gateway/HttpGatewayExample.java deleted file mode 100644 index 3002dd941..000000000 --- a/services-examples/src/main/java/io/scalecube/services/examples/gateway/HttpGatewayExample.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.scalecube.services.examples.gateway; - -import io.scalecube.services.Address; -import io.scalecube.services.gateway.Gateway; -import io.scalecube.services.gateway.GatewayOptions; -import java.net.InetSocketAddress; -import java.time.Duration; -import java.util.concurrent.ThreadLocalRandom; -import reactor.core.publisher.Mono; - -public class HttpGatewayExample implements Gateway { - - private final GatewayOptions options; - private final InetSocketAddress address; - - public HttpGatewayExample(GatewayOptions options) { - this.options = options; - this.address = new InetSocketAddress(options.port()); - } - - @Override - public String id() { - return options.id(); - } - - @Override - public Address address() { - return Address.create(address.getHostString(), address.getPort()); - } - - @Override - public Mono start() { - return Mono.defer( - () -> { - System.out.println("Starting HTTP gateway..."); - - return Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 500))) - .map(tick -> this) - .doOnSuccess(gw -> System.out.println("HTTP gateway is started on " + gw.address)); - }); - } - - @Override - public Mono stop() { - return Mono.defer( - () -> { - System.out.println("Stopping HTTP gateway..."); - return Mono.empty(); - }); - } -} diff --git a/services-examples/src/main/java/io/scalecube/services/examples/gateway/WebsocketGatewayExample.java b/services-examples/src/main/java/io/scalecube/services/examples/gateway/WebsocketGatewayExample.java deleted file mode 100644 index e067af37f..000000000 --- a/services-examples/src/main/java/io/scalecube/services/examples/gateway/WebsocketGatewayExample.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.scalecube.services.examples.gateway; - -import io.scalecube.services.Address; -import io.scalecube.services.gateway.Gateway; -import io.scalecube.services.gateway.GatewayOptions; -import java.net.InetSocketAddress; -import java.time.Duration; -import java.util.concurrent.ThreadLocalRandom; -import reactor.core.publisher.Mono; - -public class WebsocketGatewayExample implements Gateway { - - private final GatewayOptions options; - private final InetSocketAddress address; - - public WebsocketGatewayExample(GatewayOptions options) { - this.options = options; - this.address = new InetSocketAddress(options.port()); - } - - @Override - public String id() { - return options.id(); - } - - @Override - public Address address() { - return Address.create(address.getHostString(), address.getPort()); - } - - @Override - public Mono start() { - return Mono.defer( - () -> { - System.out.println("Starting WS gateway..."); - - return Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 500))) - .map(tick -> this) - .doOnSuccess(gw -> System.out.println("WS gateway is started on " + gw.address)); - }); - } - - @Override - public Mono stop() { - return Mono.defer( - () -> { - System.out.println("Stopping WS gateway..."); - return Mono.empty(); - }); - } -} diff --git a/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example1.java b/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example1.java index e20249ff9..3064704a9 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example1.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example1.java @@ -2,12 +2,12 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.examples.helloworld.service.GreetingServiceImpl; import io.scalecube.services.examples.helloworld.service.api.GreetingsService; import io.scalecube.services.transport.rsocket.RSocketServiceTransport; import io.scalecube.transport.netty.websocket.WebsocketTransportFactory; -import reactor.core.publisher.Mono; /** * The Hello World project is a time-honored tradition in computer programming. It is a simple @@ -27,29 +27,29 @@ public class Example1 { public static void main(String[] args) { // ScaleCube Node with no members Microservices seed = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); final Address seedAddress = seed.discoveryAddress(); // Construct a ScaleCube node which joins the cluster hosting the Greeting Service Microservices ms = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); // Create service proxy GreetingsService service = seed.call().api(GreetingsService.class); @@ -57,6 +57,7 @@ public static void main(String[] args) { // Execute the services and subscribe to service events service.sayHello("joe").subscribe(consumer -> System.out.println(consumer.message())); - Mono.whenDelayError(seed.shutdown(), ms.shutdown()).block(); + seed.close(); + ms.close(); } } diff --git a/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example2.java b/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example2.java index 7bd9aed60..a77c8761f 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example2.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example2.java @@ -2,6 +2,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; @@ -34,29 +35,29 @@ public class Example2 { public static void main(String[] args) { // ScaleCube Node node with no members Microservices seed = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); // Construct a ScaleCube node which joins the cluster hosting the Greeting Service final Address seedAddress = seed.discoveryAddress(); Microservices ms = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); // Create a proxy to the seed service node ServiceCall service = seed.call(); @@ -76,6 +77,7 @@ public static void main(String[] args) { System.out.println(greeting.message()); }); - Mono.whenDelayError(seed.shutdown(), ms.shutdown()).block(); + seed.close(); + ms.close(); } } diff --git a/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example3.java b/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example3.java index 7fc0b7a8a..89dc74949 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example3.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/helloworld/Example3.java @@ -2,13 +2,13 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.examples.helloworld.service.BidiGreetingImpl; import io.scalecube.services.examples.helloworld.service.api.BidiGreetingService; import io.scalecube.services.transport.rsocket.RSocketServiceTransport; import io.scalecube.transport.netty.websocket.WebsocketTransportFactory; import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; /** * The Hello World project is a time-honored tradition in computer programming. It is a simple @@ -28,29 +28,29 @@ public class Example3 { public static void main(String[] args) { // ScaleCube Node with no members Microservices seed = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); final Address seedAddress = seed.discoveryAddress(); // Construct a ScaleCube node which joins the cluster hosting the Greeting Service Microservices ms = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new BidiGreetingImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new BidiGreetingImpl())); // Create service proxy BidiGreetingService service = seed.call().api(BidiGreetingService.class); @@ -61,6 +61,7 @@ public static void main(String[] args) { .doOnNext(System.out::println) .blockLast(); - Mono.whenDelayError(seed.shutdown(), ms.shutdown()).block(); + seed.close(); + ms.close(); } } diff --git a/services-examples/src/main/java/io/scalecube/services/examples/services/Example1.java b/services-examples/src/main/java/io/scalecube/services/examples/services/Example1.java index 1d61f73e5..d2aa8dba9 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/services/Example1.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/services/Example1.java @@ -2,10 +2,10 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.transport.rsocket.RSocketServiceTransport; import io.scalecube.transport.netty.websocket.WebsocketTransportFactory; -import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; public class Example1 { @@ -17,40 +17,40 @@ public class Example1 { */ public static void main(String[] args) { Microservices gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); final Address gatewayAddress = gateway.discoveryAddress(); Microservices service2Node = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new Service2Impl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new Service2Impl())); Microservices service1Node = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new Service1Impl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new Service1Impl())); gateway .call() @@ -63,7 +63,8 @@ public static void main(String[] args) { .log("complete |") .block(); - Mono.whenDelayError(gateway.shutdown(), service1Node.shutdown(), service2Node.shutdown()) - .block(); + gateway.close(); + service1Node.close(); + service2Node.close(); } } diff --git a/services-examples/src/main/java/io/scalecube/services/examples/services/Example2.java b/services-examples/src/main/java/io/scalecube/services/examples/services/Example2.java index 670372245..643e43fd2 100644 --- a/services-examples/src/main/java/io/scalecube/services/examples/services/Example2.java +++ b/services-examples/src/main/java/io/scalecube/services/examples/services/Example2.java @@ -2,10 +2,10 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.transport.rsocket.RSocketServiceTransport; import io.scalecube.transport.netty.websocket.WebsocketTransportFactory; -import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; public class Example2 { @@ -17,40 +17,40 @@ public class Example2 { */ public static void main(String[] args) { Microservices gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); final Address gatewayAddress = gateway.discoveryAddress(); Microservices service2Node = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new Service2Impl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new Service2Impl())); Microservices service1Node = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new Service1Impl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new Service1Impl())); gateway .call() @@ -63,7 +63,8 @@ public static void main(String[] args) { .log("complete |") .block(); - Mono.whenDelayError(gateway.shutdown(), service1Node.shutdown(), service2Node.shutdown()) - .block(); + gateway.close(); + service1Node.close(); + service2Node.close(); } } diff --git a/services-gateway/pom.xml b/services-gateway/pom.xml index 8bfff3973..f49ecc333 100644 --- a/services-gateway/pom.xml +++ b/services-gateway/pom.xml @@ -42,10 +42,6 @@ org.jctools jctools-core - - org.slf4j - slf4j-api - @@ -79,12 +75,12 @@ org.apache.logging.log4j - log4j-core + log4j-jpl test - com.lmax - disruptor + org.apache.logging.log4j + log4j-core test diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/GatewaySessionHandler.java b/services-gateway/src/main/java/io/scalecube/services/gateway/GatewaySessionHandler.java index 650894d59..dbe6d2be5 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/GatewaySessionHandler.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/GatewaySessionHandler.java @@ -2,15 +2,15 @@ import io.netty.buffer.ByteBuf; import io.scalecube.services.api.ServiceMessage; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.publisher.Mono; import reactor.util.context.Context; public interface GatewaySessionHandler { - Logger LOGGER = LoggerFactory.getLogger(GatewaySessionHandler.class); + Logger LOGGER = System.getLogger(GatewaySessionHandler.class.getName()); GatewaySessionHandler DEFAULT_INSTANCE = new GatewaySessionHandler() {}; @@ -59,8 +59,9 @@ default void onResponse( * @param context subscriber context */ default void onError(GatewaySession session, Throwable throwable, Context context) { - LOGGER.error( - "Exception occurred on session: {}, on context: {}, cause:", + LOGGER.log( + Level.ERROR, + "Exception occurred on session: {0,number,#}, on context: {1}", session.sessionId(), context, throwable); @@ -73,7 +74,8 @@ default void onError(GatewaySession session, Throwable throwable, Context contex * @param throwable an exception that occurred (not null) */ default void onSessionError(GatewaySession session, Throwable throwable) { - LOGGER.error("Exception occurred on session: {}, cause:", session.sessionId(), throwable); + LOGGER.log( + Level.ERROR, "Exception occurred on session: {0,number,#}", session.sessionId(), throwable); } /** @@ -86,8 +88,11 @@ default void onSessionError(GatewaySession session, Throwable throwable) { default Mono onConnectionOpen(long sessionId, Map headers) { return Mono.fromRunnable( () -> - LOGGER.debug( - "Connection opened, sessionId: {}, headers({})", sessionId, headers.size())); + LOGGER.log( + Level.DEBUG, + "Connection opened, sessionId: {0,number,#}, headers({1})", + sessionId, + headers.size())); } /** @@ -96,7 +101,7 @@ default Mono onConnectionOpen(long sessionId, Map headers) * @param session websocket session (not null) */ default void onSessionOpen(GatewaySession session) { - LOGGER.info("Session opened: {}", session); + LOGGER.log(Level.INFO, "Session opened: {0}", session); } /** @@ -105,6 +110,6 @@ default void onSessionOpen(GatewaySession session) { * @param session websocket session (not null) */ default void onSessionClose(GatewaySession session) { - LOGGER.info("Session closed: {}", session); + LOGGER.log(Level.INFO, "Session closed: {0}", session); } } diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/ReferenceCountUtil.java b/services-gateway/src/main/java/io/scalecube/services/gateway/ReferenceCountUtil.java index 1c534365e..9e8884e1c 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/ReferenceCountUtil.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/ReferenceCountUtil.java @@ -1,12 +1,12 @@ package io.scalecube.services.gateway; import io.netty.util.ReferenceCounted; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; public final class ReferenceCountUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(ReferenceCountUtil.class); + private static final Logger LOGGER = System.getLogger(ReferenceCountUtil.class.getName()); private ReferenceCountUtil() { // Do not instantiate @@ -24,7 +24,11 @@ public static boolean safestRelease(Object msg) { && ((ReferenceCounted) msg).refCnt() > 0 && ((ReferenceCounted) msg).release(); } catch (Throwable t) { - LOGGER.warn("Failed to release reference counted object: {}, cause: {}", msg, t.toString()); + LOGGER.log( + Level.WARNING, + "Failed to release reference counted object: {0}, cause: {1}", + msg, + t.toString()); return false; } } diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/client/http/HttpGatewayClientTransport.java b/services-gateway/src/main/java/io/scalecube/services/gateway/client/http/HttpGatewayClientTransport.java index ae7655f35..eea2b4c69 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/client/http/HttpGatewayClientTransport.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/client/http/HttpGatewayClientTransport.java @@ -13,6 +13,8 @@ import io.scalecube.services.transport.api.ClientChannel; import io.scalecube.services.transport.api.ClientTransport; import io.scalecube.services.transport.api.DataCodec; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.lang.reflect.Type; import java.time.Duration; import java.util.Map; @@ -20,8 +22,6 @@ import java.util.function.Function; import java.util.function.UnaryOperator; import org.reactivestreams.Publisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.netty.NettyOutbound; @@ -33,7 +33,7 @@ public final class HttpGatewayClientTransport implements ClientChannel, ClientTransport { - private static final Logger LOGGER = LoggerFactory.getLogger(HttpGatewayClientTransport.class); + private static final Logger LOGGER = System.getLogger(HttpGatewayClientTransport.class.getName()); private static final String CONTENT_TYPE = "application/json"; private static final HttpGatewayClientCodec CLIENT_CODEC = @@ -93,7 +93,7 @@ public Mono requestResponse(ServiceMessage request, Type respons private Mono send( ServiceMessage request, HttpClientRequest clientRequest, NettyOutbound outbound) { - LOGGER.debug("Sending request: {}", request); + LOGGER.log(Level.DEBUG, "Sending request: {0}", request); // prepare request headers request.headers().forEach(clientRequest::header); // send with publisher (defer buffer cleanup to netty) @@ -127,7 +127,7 @@ private static ServiceMessage toMessage(HttpClientResponse httpResponse, ByteBuf .forEach(entry -> builder.header(entry.getKey(), entry.getValue())); ServiceMessage message = builder.build(); - LOGGER.debug("Received response: {}", message); + LOGGER.log(Level.DEBUG, "Received response: {0}", message); return message; } diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/client/websocket/WebsocketGatewayClientSession.java b/services-gateway/src/main/java/io/scalecube/services/gateway/client/websocket/WebsocketGatewayClientSession.java index 24c637c35..3d67cde36 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/client/websocket/WebsocketGatewayClientSession.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/client/websocket/WebsocketGatewayClientSession.java @@ -8,13 +8,13 @@ import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.gateway.ReferenceCountUtil; import io.scalecube.services.gateway.client.GatewayClientCodec; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.nio.channels.ClosedChannelException; import java.time.Duration; import java.util.Map; import java.util.StringJoiner; import org.jctools.maps.NonBlockingHashMapLong; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; import reactor.core.publisher.Sinks.Many; @@ -25,7 +25,8 @@ public final class WebsocketGatewayClientSession { - private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketGatewayClientSession.class); + private static final Logger LOGGER = + System.getLogger(WebsocketGatewayClientSession.class.getName()); private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); @@ -61,13 +62,14 @@ public final class WebsocketGatewayClientSession { try { message = clientCodec.decode(byteBuf); } catch (Exception ex) { - LOGGER.error("Response decoder failed:", ex); + LOGGER.log(Level.ERROR, "Response decoder failed", ex); return; } // ignore messages w/o sid if (!message.headers().containsKey(STREAM_ID)) { - LOGGER.error("Ignore response: {} with null sid, session={}", message, id); + LOGGER.log( + Level.ERROR, "Ignore response: {0} with null sid, session={1}", message, id); if (message.data() != null) { ReferenceCountUtil.safestRelease(message.data()); } @@ -103,18 +105,18 @@ Many newUnicastProcessor(long sid) { } private One newMonoProcessor0(long sid) { - LOGGER.debug("Put sid={}, session={}", sid, id); + LOGGER.log(Level.DEBUG, "Put sid={0}, session={1}", sid, id); return Sinks.one(); } private Many newUnicastProcessor0(long sid) { - LOGGER.debug("Put sid={}, session={}", sid, id); + LOGGER.log(Level.DEBUG, "Put sid={0}, session={1}", sid, id); return Sinks.many().unicast().onBackpressureBuffer(); } void removeProcessor(long sid) { if (inboundProcessors.remove(sid) != null) { - LOGGER.debug("Removed sid={}, session={}", sid, id); + LOGGER.log(Level.DEBUG, "Removed sid={0}, session={1}", sid, id); } } @@ -135,7 +137,11 @@ void cancel(long sid, String qualifier) { .subscribe( null, th -> - LOGGER.error("Exception occurred on sending CANCEL signal for session={}", id, th)); + LOGGER.log( + Level.ERROR, + "Exception occurred on sending CANCEL signal for session={0}", + id, + th)); } /** @@ -155,9 +161,7 @@ public Mono onClose() { } private void handleResponse(ServiceMessage response, Object processor) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Handle response: {}, session={}", response, id); - } + LOGGER.log(Level.DEBUG, "Handle response: {0}, session={1}", response, id); try { Signal signal = null; diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/client/websocket/WebsocketGatewayClientTransport.java b/services-gateway/src/main/java/io/scalecube/services/gateway/client/websocket/WebsocketGatewayClientTransport.java index a9a892b0a..1c2d22f83 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/client/websocket/WebsocketGatewayClientTransport.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/client/websocket/WebsocketGatewayClientTransport.java @@ -11,6 +11,8 @@ import io.scalecube.services.gateway.client.ServiceMessageCodec; import io.scalecube.services.transport.api.ClientChannel; import io.scalecube.services.transport.api.ClientTransport; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.lang.reflect.Type; import java.time.Duration; import java.util.Map; @@ -19,8 +21,6 @@ import java.util.function.Function; import java.util.function.UnaryOperator; import org.reactivestreams.Publisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.netty.Connection; @@ -31,7 +31,7 @@ public final class WebsocketGatewayClientTransport implements ClientChannel, ClientTransport { private static final Logger LOGGER = - LoggerFactory.getLogger(WebsocketGatewayClientTransport.class); + System.getLogger(WebsocketGatewayClientTransport.class.getName()); private static final String STREAM_ID = "sid"; private static final String CONTENT_TYPE = "application/json"; @@ -97,21 +97,23 @@ private WebsocketGatewayClientSession clientSession(HttpClient httpClient) { connection -> { final WebsocketGatewayClientSession session = new WebsocketGatewayClientSession(clientCodec, connection); - LOGGER.info("Created session: {}", session); + LOGGER.log(Level.INFO, "Created session: {0}", session); // setup shutdown hook session .onClose() - .doOnTerminate(() -> LOGGER.info("Closed session: {}", session)) + .doOnTerminate(() -> LOGGER.log(Level.INFO, "Closed session: {0}", session)) .subscribe( null, th -> - LOGGER.warn( - "Exception on closing session: {}, cause: {}", + LOGGER.log( + Level.WARNING, + "Exception on closing session: {0}, cause: {1}", session, th.toString())); return session; }) - .doOnError(ex -> LOGGER.warn("Failed to connect, cause: {}", ex.toString())) + .doOnError( + ex -> LOGGER.log(Level.WARNING, "Failed to connect, cause: {0}", ex.toString())) .toFuture() .get(); } catch (Exception e) { @@ -127,7 +129,7 @@ public Mono requestResponse(ServiceMessage request, Type respons final WebsocketGatewayClientSession session = clientSessionReference.get(); return session .send(encodeRequest(request, sid)) - .doOnSubscribe(s -> LOGGER.debug("Sending request {}", request)) + .doOnSubscribe(s -> LOGGER.log(Level.DEBUG, "Sending request {0}", request)) .then(session.newMonoProcessor(sid).asMono()) .map(msg -> ServiceMessageCodec.decodeData(msg, responseType)) .doOnCancel(() -> session.cancel(sid, request.qualifier())) @@ -143,7 +145,7 @@ public Flux requestStream(ServiceMessage request, Type responseT final WebsocketGatewayClientSession session = clientSessionReference.get(); return session .send(encodeRequest(request, sid)) - .doOnSubscribe(s -> LOGGER.debug("Sending request {}", request)) + .doOnSubscribe(s -> LOGGER.log(Level.DEBUG, "Sending request {0}", request)) .thenMany(session.newUnicastProcessor(sid).asFlux()) .map(msg -> ServiceMessageCodec.decodeData(msg, responseType)) .doOnCancel(() -> session.cancel(sid, request.qualifier())) diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/http/HttpGateway.java b/services-gateway/src/main/java/io/scalecube/services/gateway/http/HttpGateway.java index 272232b5c..d7c196da3 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/http/HttpGateway.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/http/HttpGateway.java @@ -11,8 +11,6 @@ import java.net.InetSocketAddress; import java.util.StringJoiner; import java.util.function.Consumer; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; import reactor.netty.DisposableServer; import reactor.netty.http.server.HttpServer; import reactor.netty.resources.LoopResources; @@ -40,20 +38,25 @@ public String id() { } @Override - public Mono start() { - return Mono.defer( - () -> { - HttpGatewayAcceptor gatewayAcceptor = - new HttpGatewayAcceptor(options.call(), errorMapper); - - loopResources = LoopResources.create(options.id() + ":" + options.port()); - - return prepareHttpServer(loopResources, options.port()) - .handle(gatewayAcceptor) - .bind() - .doOnSuccess(server -> this.server = server) - .thenReturn(this); - }); + public Gateway start() { + HttpGatewayAcceptor gatewayAcceptor = new HttpGatewayAcceptor(options.call(), errorMapper); + + loopResources = + LoopResources.create( + options.id() + ":" + options.port(), LoopResources.DEFAULT_IO_WORKER_COUNT, true); + + try { + prepareHttpServer(loopResources, options.port()) + .handle(gatewayAcceptor) + .bind() + .doOnSuccess(server -> this.server = server) + .toFuture() + .get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return this; } private HttpServer prepareHttpServer(LoopResources loopResources, int port) { @@ -80,24 +83,21 @@ public Address address() { } @Override - public Mono stop() { - return Flux.concatDelayError(shutdownServer(server), shutdownLoopResources(loopResources)) - .then(); + public void stop() { + shutdownServer(server); + shutdownLoopResources(loopResources); } - private Mono shutdownServer(DisposableServer server) { - return Mono.defer( - () -> { - if (server != null) { - server.dispose(); - return server.onDispose(); - } - return Mono.empty(); - }); + private void shutdownServer(DisposableServer server) { + if (server != null) { + server.dispose(); + } } - private Mono shutdownLoopResources(LoopResources loopResources) { - return loopResources != null ? loopResources.disposeLater() : Mono.empty(); + private void shutdownLoopResources(LoopResources loopResources) { + if (loopResources != null) { + loopResources.dispose(); + } } @Override @@ -162,7 +162,7 @@ public Builder corsConfigBuilder(CorsConfigBuilder corsConfigBuilder) { } public Builder corsConfigBuilder(Consumer consumer) { - consumer.accept(this.corsConfigBuilder); + consumer.accept(corsConfigBuilder); return this; } diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/http/HttpGatewayAcceptor.java b/services-gateway/src/main/java/io/scalecube/services/gateway/http/HttpGatewayAcceptor.java index 3a04f22de..8ba85b7fb 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/http/HttpGatewayAcceptor.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/http/HttpGatewayAcceptor.java @@ -18,10 +18,10 @@ import io.scalecube.services.exceptions.ServiceProviderErrorMapper; import io.scalecube.services.gateway.ReferenceCountUtil; import io.scalecube.services.transport.api.DataCodec; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.util.function.BiFunction; import org.reactivestreams.Publisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.publisher.Mono; import reactor.netty.ByteBufMono; import reactor.netty.http.server.HttpServerRequest; @@ -30,7 +30,7 @@ public class HttpGatewayAcceptor implements BiFunction> { - private static final Logger LOGGER = LoggerFactory.getLogger(HttpGatewayAcceptor.class); + private static final Logger LOGGER = System.getLogger(HttpGatewayAcceptor.class.getName()); private static final String ERROR_NAMESPACE = "io.scalecube.services.error"; @@ -48,8 +48,9 @@ public class HttpGatewayAcceptor @Override public Publisher apply(HttpServerRequest httpRequest, HttpServerResponse httpResponse) { - LOGGER.debug( - "Accepted request: {}, headers: {}, params: {}", + LOGGER.log( + Level.DEBUG, + "Accepted request: {0}, headers: {}, params: {1}", httpRequest, httpRequest.requestHeaders(), httpRequest.params()); @@ -132,7 +133,7 @@ private ByteBuf encodeData(Object data, String dataFormat) { DataCodec.getInstance(dataFormat).encode(new ByteBufOutputStream(byteBuf), data); } catch (Throwable t) { ReferenceCountUtil.safestRelease(byteBuf); - LOGGER.error("Failed to encode data: {}", data, t); + LOGGER.log(Level.ERROR, "Failed to encode data: {0}", data, t); return Unpooled.EMPTY_BUFFER; } diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/websocket/WebsocketGateway.java b/services-gateway/src/main/java/io/scalecube/services/gateway/websocket/WebsocketGateway.java index d3beb6ef8..07e449dfa 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/websocket/WebsocketGateway.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/websocket/WebsocketGateway.java @@ -11,8 +11,6 @@ import java.time.Duration; import java.util.StringJoiner; import java.util.function.UnaryOperator; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; import reactor.netty.Connection; import reactor.netty.DisposableServer; import reactor.netty.http.server.HttpServer; @@ -45,21 +43,28 @@ public String id() { } @Override - public Mono start() { - return Mono.defer( - () -> { - WebsocketGatewayAcceptor gatewayAcceptor = - new WebsocketGatewayAcceptor(options.call(), gatewayHandler, errorMapper); - - loopResources = LoopResources.create(options.id() + ":" + options.port()); - - return prepareHttpServer(loopResources, options.port()) - .doOnConnection(this::setupKeepAlive) - .handle(gatewayAcceptor) - .bind() - .doOnSuccess(server -> this.server = server) - .thenReturn(this); - }); + public Gateway start() { + WebsocketGatewayAcceptor gatewayAcceptor = + new WebsocketGatewayAcceptor(options.call(), gatewayHandler, errorMapper); + + loopResources = + LoopResources.create( + options.id() + ":" + options.port(), LoopResources.DEFAULT_IO_WORKER_COUNT, true); + + try { + prepareHttpServer(loopResources, options.port()) + .doOnConnection(this::setupKeepAlive) + .handle(gatewayAcceptor) + .bind() + .doOnSuccess(server -> this.server = server) + .thenReturn(this) + .toFuture() + .get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return this; } private HttpServer prepareHttpServer(LoopResources loopResources, int port) { @@ -80,24 +85,21 @@ public Address address() { } @Override - public Mono stop() { - return Flux.concatDelayError(shutdownServer(server), shutdownLoopResources(loopResources)) - .then(); + public void stop() { + shutdownServer(server); + shutdownLoopResources(loopResources); } - private Mono shutdownServer(DisposableServer server) { - return Mono.defer( - () -> { - if (server != null) { - server.dispose(); - return server.onDispose(); - } - return Mono.empty(); - }); + private void shutdownServer(DisposableServer server) { + if (server != null) { + server.dispose(); + } } - private Mono shutdownLoopResources(LoopResources loopResources) { - return loopResources != null ? loopResources.disposeLater() : Mono.empty(); + private void shutdownLoopResources(LoopResources loopResources) { + if (loopResources != null) { + loopResources.dispose(); + } } private void setupKeepAlive(Connection connection) { diff --git a/services-gateway/src/main/java/io/scalecube/services/gateway/websocket/WebsocketGatewaySession.java b/services-gateway/src/main/java/io/scalecube/services/gateway/websocket/WebsocketGatewaySession.java index 1d97d9db1..80d96ff3f 100644 --- a/services-gateway/src/main/java/io/scalecube/services/gateway/websocket/WebsocketGatewaySession.java +++ b/services-gateway/src/main/java/io/scalecube/services/gateway/websocket/WebsocketGatewaySession.java @@ -5,13 +5,13 @@ import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.gateway.GatewaySession; import io.scalecube.services.gateway.GatewaySessionHandler; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.function.Predicate; import org.jctools.maps.NonBlockingHashMapLong; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -21,7 +21,7 @@ public final class WebsocketGatewaySession implements GatewaySession { - private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketGatewaySession.class); + private static final Logger LOGGER = System.getLogger(WebsocketGatewaySession.class.getName()); private static final Predicate SEND_PREDICATE = f -> true; @@ -174,9 +174,11 @@ public boolean dispose(Long streamId) { Disposable disposable = subscriptions.remove(streamId); result = disposable != null; if (result) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Dispose subscription by sid={}, session={}", streamId, sessionId); - } + LOGGER.log( + Level.DEBUG, + "Dispose subscription by sid={0,number,#}, session={1,number,#}", + streamId, + sessionId); disposable.dispose(); } } @@ -200,16 +202,16 @@ public void register(Long streamId, Disposable disposable) { result = subscriptions.putIfAbsent(streamId, disposable) == null; } if (result) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Registered subscription by sid={}, session={}", streamId, sessionId); - } + LOGGER.log( + Level.DEBUG, + "Registered subscription by sid={0,number,#}, session={1,number,#}", + streamId, + sessionId); } } private void clearSubscriptions() { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Clear subscriptions on session={}", sessionId); - } + LOGGER.log(Level.DEBUG, "Clear subscriptions on session={0,number,#}", sessionId); subscriptions.forEach((sid, disposable) -> disposable.dispose()); subscriptions.clear(); } diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/GatewaySessionHandlerImpl.java b/services-gateway/src/test/java/io/scalecube/services/gateway/GatewaySessionHandlerImpl.java index f036f1049..d49ed1f3a 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/GatewaySessionHandlerImpl.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/GatewaySessionHandlerImpl.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.auth.Authenticator; +import java.lang.System.Logger.Level; import java.util.Optional; import reactor.util.context.Context; @@ -30,12 +31,12 @@ public ServiceMessage mapMessage( @Override public void onSessionOpen(GatewaySession s) { - LOGGER.info("Session opened: {}", s); + LOGGER.log(Level.INFO, "Session opened: {0}", s); } @Override public void onSessionClose(GatewaySession session) { - LOGGER.info("Session removed: {}", session); + LOGGER.log(Level.INFO, "Session removed: {0}", session); authRegistry.removeAuth(session.sessionId()); } } diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/http/CorsTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/http/CorsTest.java index b22da4be8..e8e6a654d 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/http/CorsTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/http/CorsTest.java @@ -9,6 +9,7 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.examples.GreetingService; import io.scalecube.services.examples.GreetingServiceImpl; import io.scalecube.services.gateway.BaseTest; @@ -37,7 +38,7 @@ void setUp() { @AfterEach void afterEach() { if (gateway != null) { - gateway.shutdown().block(); + gateway.close(); } if (connectionProvider != null) { connectionProvider.dispose(); @@ -47,19 +48,19 @@ void afterEach() { @Test void testCrossOriginRequest() { gateway = - Microservices.builder() - .gateway( - opts -> - new HttpGateway.Builder() - .options(opts.id("http")) - .corsEnabled(true) - .corsConfigBuilder( - builder -> - builder.allowedRequestHeaders("Content-Type", "X-Correlation-ID")) - .build()) - .services(new GreetingServiceImpl()) - .start() - .block(TIMEOUT); + Microservices.start( + new Context() + .gateway( + opts -> + new HttpGateway.Builder() + .options(opts.id("http")) + .corsEnabled(true) + .corsConfigBuilder( + builder -> + builder.allowedRequestHeaders( + "Content-Type", "X-Correlation-ID")) + .build()) + .services(new GreetingServiceImpl())); final HttpClient client = newClient(gateway.gateway("http").address()); @@ -111,11 +112,10 @@ private HttpClient newClient(final Address address) { @Test void testOptionRequestCorsDisabled() { gateway = - Microservices.builder() - .gateway(opts -> new HttpGateway.Builder().options(opts.id("http")).build()) - .services(new GreetingServiceImpl()) - .start() - .block(TIMEOUT); + Microservices.start( + new Context() + .gateway(opts -> new HttpGateway.Builder().options(opts.id("http")).build()) + .services(new GreetingServiceImpl())); final HttpClient client = newClient(gateway.gateway("http").address()); diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpClientConnectionTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpClientConnectionTest.java index 77a5ae0fd..faabdfd44 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpClientConnectionTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpClientConnectionTest.java @@ -4,6 +4,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.annotations.Service; import io.scalecube.services.annotations.ServiceMethod; @@ -19,7 +20,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -36,39 +36,36 @@ class HttpClientConnectionTest extends BaseTest { @BeforeEach void beforEach() { gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .gateway(options -> new HttpGateway.Builder().options(options.id("HTTP")).build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .gateway(options -> new HttpGateway.Builder().options(options.id("HTTP")).build())); gatewayAddress = gateway.gateway("HTTP").address(); microservices = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint)) - .membership( - opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) - .transport(RSocketServiceTransport::new) - .services(new TestServiceImpl(onCancelCounter)) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint)) + .membership( + opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) + .transport(RSocketServiceTransport::new) + .services(new TestServiceImpl(onCancelCounter))); } @AfterEach void afterEach() { - Flux.concat( - Mono.justOrEmpty(gateway).map(Microservices::shutdown), - Mono.justOrEmpty(microservices).map(Microservices::shutdown)) - .then() - .block(); + gateway.close(); + microservices.close(); } @Test diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpGatewayTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpGatewayTest.java index c0d90ef15..09076a57b 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpGatewayTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpGatewayTest.java @@ -5,6 +5,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.ServiceInfo; import io.scalecube.services.api.Qualifier; @@ -49,40 +50,40 @@ class HttpGatewayTest extends BaseTest { @BeforeAll static void beforeAll() { gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .gateway( - options -> - new HttpGateway.Builder() - .options(options.id("HTTP")) - .errorMapper(ERROR_MAPPER) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .gateway( + options -> + new HttpGateway.Builder() + .options(options.id("HTTP")) + .errorMapper(ERROR_MAPPER) + .build())); gatewayAddress = gateway.gateway("HTTP").address(); router = new StaticAddressRouter(gatewayAddress); microservices = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint)) - .membership( - opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .services( - ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) - .errorMapper(ERROR_MAPPER) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint)) + .membership( + opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl()) + .services( + ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) + .errorMapper(ERROR_MAPPER) + .build())); } @BeforeEach diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpLocalGatewayTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpLocalGatewayTest.java index 382b01b34..211b9a00d 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpLocalGatewayTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/http/HttpLocalGatewayTest.java @@ -5,6 +5,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.ServiceInfo; import io.scalecube.services.api.Qualifier; @@ -45,14 +46,14 @@ class HttpLocalGatewayTest extends BaseTest { @BeforeAll static void beforeAll() { gateway = - Microservices.builder() - .gateway(options -> new HttpGateway.Builder().options(options.id("HTTP")).build()) - .services(new GreetingServiceImpl()) - .services( - ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) - .errorMapper(ERROR_MAPPER) - .build()) - .startAwait(); + Microservices.start( + new Context() + .gateway(options -> new HttpGateway.Builder().options(options.id("HTTP")).build()) + .services(new GreetingServiceImpl()) + .services( + ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) + .errorMapper(ERROR_MAPPER) + .build())); gatewayAddress = gateway.gateway("HTTP").address(); router = new StaticAddressRouter(gatewayAddress); } diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketClientConnectionTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketClientConnectionTest.java index e3544c5fe..7a57d5280 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketClientConnectionTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketClientConnectionTest.java @@ -7,6 +7,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.gateway.BaseTest; @@ -26,7 +27,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -44,46 +44,43 @@ class WebsocketClientConnectionTest extends BaseTest { @BeforeEach void beforEach() { gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .gateway( - options -> - new WebsocketGateway.Builder() - .options(options.id("WS")) - .gatewayHandler(sessionEventHandler) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .gateway( + options -> + new WebsocketGateway.Builder() + .options(options.id("WS")) + .gatewayHandler(sessionEventHandler) + .build())); gatewayAddress = gateway.gateway("WS").address(); microservices = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint)) - .membership( - opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) - .transport(RSocketServiceTransport::new) - .services(new TestServiceImpl(onCloseCounter::incrementAndGet)) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint)) + .membership( + opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) + .transport(RSocketServiceTransport::new) + .services(new TestServiceImpl(onCloseCounter::incrementAndGet))); onCloseCounter.set(0); } @AfterEach void afterEach() { - Flux.concat( - Mono.justOrEmpty(gateway).map(Microservices::shutdown), - Mono.justOrEmpty(microservices).map(Microservices::shutdown)) - .then() - .block(); + gateway.close(); + microservices.close(); } @Test diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketClientTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketClientTest.java index 9abc137b5..f841adee6 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketClientTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketClientTest.java @@ -4,6 +4,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.ServiceInfo; import io.scalecube.services.annotations.Service; @@ -25,7 +26,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; import reactor.test.StepVerifier; class WebsocketClientTest extends BaseTest { @@ -39,48 +39,45 @@ class WebsocketClientTest extends BaseTest { @BeforeAll static void beforeAll() { gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .gateway( - options -> - new WebsocketGateway.Builder() - .options(options.id("WS")) - .gatewayHandler(new TestGatewaySessionHandler()) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .gateway( + options -> + new WebsocketGateway.Builder() + .options(options.id("WS")) + .gatewayHandler(new TestGatewaySessionHandler()) + .build())); gatewayAddress = gateway.gateway("WS").address(); microservices = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint)) - .membership( - opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) - .transport(RSocketServiceTransport::new) - .services(new TestServiceImpl()) - .services( - ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) - .errorMapper(ERROR_MAPPER) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint)) + .membership( + opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) + .transport(RSocketServiceTransport::new) + .services(new TestServiceImpl()) + .services( + ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) + .errorMapper(ERROR_MAPPER) + .build())); } @AfterAll static void afterAll() { - Flux.concat( - Mono.justOrEmpty(gateway).map(Microservices::shutdown), - Mono.justOrEmpty(microservices).map(Microservices::shutdown)) - .then() - .block(); + gateway.close(); + microservices.close(); } @Test diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketGatewayAuthTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketGatewayAuthTest.java index eae73b47a..623dd7d99 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketGatewayAuthTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketGatewayAuthTest.java @@ -6,6 +6,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.exceptions.ForbiddenException; @@ -44,15 +45,15 @@ public class WebsocketGatewayAuthTest { @BeforeAll static void beforeAll() { gateway = - Microservices.builder() - .gateway( - options -> - new WebsocketGateway.Builder() - .options(options.id("WS")) - .gatewayHandler(new GatewaySessionHandlerImpl(AUTH_REGISTRY)) - .build()) - .services(new SecuredServiceImpl(AUTH_REGISTRY)) - .startAwait(); + Microservices.start( + new Context() + .gateway( + options -> + new WebsocketGateway.Builder() + .options(options.id("WS")) + .gatewayHandler(new GatewaySessionHandlerImpl(AUTH_REGISTRY)) + .build()) + .services(new SecuredServiceImpl(AUTH_REGISTRY))); } @BeforeEach diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketGatewayTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketGatewayTest.java index 1e10f9148..4b2bae311 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketGatewayTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketGatewayTest.java @@ -4,6 +4,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.ServiceInfo; import io.scalecube.services.api.Qualifier; @@ -51,35 +52,36 @@ class WebsocketGatewayTest extends BaseTest { @BeforeAll static void beforeAll() { gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .gateway(options -> new WebsocketGateway.Builder().options(options.id("WS")).build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .gateway( + options -> new WebsocketGateway.Builder().options(options.id("WS")).build())); gatewayAddress = gateway.gateway("WS").address(); router = new StaticAddressRouter(gatewayAddress); microservices = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint)) - .membership( - opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .services( - ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) - .errorMapper(ERROR_MAPPER) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint)) + .membership( + opts -> opts.seedMembers(gateway.discoveryAddress().toString()))) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl()) + .services( + ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) + .errorMapper(ERROR_MAPPER) + .build())); } @BeforeEach diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketLocalGatewayTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketLocalGatewayTest.java index 52cce13b4..b6ca3331f 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketLocalGatewayTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketLocalGatewayTest.java @@ -4,6 +4,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.ServiceInfo; import io.scalecube.services.api.Qualifier; @@ -47,19 +48,21 @@ class WebsocketLocalGatewayTest extends BaseTest { @BeforeAll static void beforeAll() { gateway = - Microservices.builder() - .gateway( - options -> - new WebsocketGateway.Builder() - .options(options.id("WS").call(options.call().errorMapper(ERROR_MAPPER))) + Microservices.start( + new Context() + .gateway( + options -> + new WebsocketGateway.Builder() + .options( + options.id("WS").call(options.call().errorMapper(ERROR_MAPPER))) + .errorMapper(ERROR_MAPPER) + .build()) + .services(new GreetingServiceImpl()) + .services( + ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) .errorMapper(ERROR_MAPPER) - .build()) - .services(new GreetingServiceImpl()) - .services( - ServiceInfo.fromServiceInstance(new ErrorServiceImpl()) - .errorMapper(ERROR_MAPPER) - .build()) - .startAwait(); + .build())); + gatewayAddress = gateway.gateway("WS").address(); router = new StaticAddressRouter(gatewayAddress); } diff --git a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketServerTest.java b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketServerTest.java index cbbabbaca..ea87db877 100644 --- a/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketServerTest.java +++ b/services-gateway/src/test/java/io/scalecube/services/gateway/websocket/WebsocketServerTest.java @@ -2,6 +2,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.annotations.Service; import io.scalecube.services.annotations.ServiceMethod; @@ -26,15 +27,16 @@ class WebsocketServerTest extends BaseTest { @BeforeAll static void beforeAll() { gateway = - Microservices.builder() - .gateway( - options -> - new WebsocketGateway.Builder() - .options(options.id("WS")) - .gatewayHandler(new TestGatewaySessionHandler()) - .build()) - .services(new TestServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .gateway( + options -> + new WebsocketGateway.Builder() + .options(options.id("WS")) + .gatewayHandler(new TestGatewaySessionHandler()) + .build()) + .services(new TestServiceImpl())); + gatewayAddress = gateway.gateway("WS").address(); } diff --git a/services-security/src/main/java/io/scalecube/services/security/ServiceTokenAuthenticator.java b/services-security/src/main/java/io/scalecube/services/security/ServiceTokenAuthenticator.java index fc1f4e019..fb0b7e7fb 100644 --- a/services-security/src/main/java/io/scalecube/services/security/ServiceTokenAuthenticator.java +++ b/services-security/src/main/java/io/scalecube/services/security/ServiceTokenAuthenticator.java @@ -3,9 +3,9 @@ import io.scalecube.security.tokens.jwt.JwtTokenResolver; import io.scalecube.services.auth.Authenticator; import io.scalecube.services.exceptions.UnauthorizedException; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.publisher.Mono; import reactor.util.retry.Retry; @@ -16,7 +16,7 @@ */ public final class ServiceTokenAuthenticator implements Authenticator { - private static final Logger LOGGER = LoggerFactory.getLogger(ServiceTokenAuthenticator.class); + private static final Logger LOGGER = System.getLogger(ServiceTokenAuthenticator.class.getName()); private JwtTokenResolver tokenResolver; private ServiceTokenMapper tokenMapper; @@ -98,7 +98,9 @@ public Mono apply(Map credentials) { .resolve(serviceToken) .map(authDataMapper::map) .retryWhen(retryStrategy) - .doOnError(th -> LOGGER.error("Failed to authenticate, cause: {}", th.toString())) + .doOnError( + th -> + LOGGER.log(Level.ERROR, "Failed to authenticate, cause: {0}", th.toString())) .onErrorMap(th -> new UnauthorizedException("Authentication failed")) .switchIfEmpty(Mono.error(new UnauthorizedException("Authentication failed"))); }); diff --git a/services-transport-parent/services-transport-rsocket/pom.xml b/services-transport-parent/services-transport-rsocket/pom.xml index 12666d855..ec54232b9 100644 --- a/services-transport-parent/services-transport-rsocket/pom.xml +++ b/services-transport-parent/services-transport-rsocket/pom.xml @@ -15,12 +15,6 @@ scalecube-services-api ${project.version} - - - org.slf4j - slf4j-api - - io.rsocket rsocket-core diff --git a/services-transport-parent/services-transport-rsocket/src/main/java/io/scalecube/services/transport/rsocket/RSocketServiceTransport.java b/services-transport-parent/services-transport-rsocket/src/main/java/io/scalecube/services/transport/rsocket/RSocketServiceTransport.java index a1aac61ef..04f01e9b1 100644 --- a/services-transport-parent/services-transport-rsocket/src/main/java/io/scalecube/services/transport/rsocket/RSocketServiceTransport.java +++ b/services-transport-parent/services-transport-rsocket/src/main/java/io/scalecube/services/transport/rsocket/RSocketServiceTransport.java @@ -5,7 +5,6 @@ import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.concurrent.DefaultThreadFactory; -import io.netty.util.concurrent.Future; import io.scalecube.services.auth.Authenticator; import io.scalecube.services.exceptions.ConnectionClosedException; import io.scalecube.services.registry.api.ServiceRegistry; @@ -17,13 +16,11 @@ import java.util.Collection; import java.util.StringJoiner; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; -import reactor.core.publisher.Mono; -import reactor.netty.FutureMono; import reactor.netty.channel.AbortedException; import reactor.netty.resources.LoopResources; @@ -214,17 +211,8 @@ public ServiceTransport start() { @Override public void stop() { - try { - //noinspection unchecked,rawtypes - Flux.concatDelayError( - Mono.defer(() -> serverLoopResources.disposeLater()), - Mono.defer(() -> FutureMono.from((Future) eventLoopGroup.shutdownGracefully()))) - .then() - .toFuture() - .get(); - } catch (Exception e) { - throw new RuntimeException(e); - } + serverLoopResources.dispose(); + eventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS); } private EventLoopGroup newEventLoopGroup() { diff --git a/services/pom.xml b/services/pom.xml index 674e90127..9f9b7e804 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -24,10 +24,6 @@ io.projectreactor reactor-core - - org.slf4j - slf4j-api - org.jctools jctools-core @@ -66,6 +62,10 @@ log4j-slf4j-impl test + + org.apache.logging.log4j + log4j-jpl + org.apache.logging.log4j log4j-core diff --git a/services/src/main/java/io/scalecube/services/Injector.java b/services/src/main/java/io/scalecube/services/Injector.java index 0dd264383..88d724727 100644 --- a/services/src/main/java/io/scalecube/services/Injector.java +++ b/services/src/main/java/io/scalecube/services/Injector.java @@ -15,7 +15,7 @@ import reactor.core.Exceptions; /** Service Injector scan and injects beans to a given Microservices instance. */ -final class Injector { +class Injector { private Injector() { // Do not instantiate diff --git a/services/src/main/java/io/scalecube/services/Microservices.java b/services/src/main/java/io/scalecube/services/Microservices.java index edf1ab6cf..844390fd6 100644 --- a/services/src/main/java/io/scalecube/services/Microservices.java +++ b/services/src/main/java/io/scalecube/services/Microservices.java @@ -2,14 +2,11 @@ import static reactor.core.publisher.Sinks.EmitFailureHandler.busyLooping; -import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.auth.Authenticator; import io.scalecube.services.auth.PrincipalMapper; import io.scalecube.services.discovery.api.ServiceDiscovery; import io.scalecube.services.discovery.api.ServiceDiscoveryEvent; -import io.scalecube.services.discovery.api.ServiceDiscoveryEvent.Type; import io.scalecube.services.discovery.api.ServiceDiscoveryFactory; -import io.scalecube.services.discovery.api.ServiceDiscoveryOptions; import io.scalecube.services.exceptions.DefaultErrorMapper; import io.scalecube.services.exceptions.ServiceProviderErrorMapper; import io.scalecube.services.gateway.Gateway; @@ -23,30 +20,26 @@ import io.scalecube.services.transport.api.ServerTransport; import io.scalecube.services.transport.api.ServiceMessageDataDecoder; import io.scalecube.services.transport.api.ServiceTransport; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.net.InetAddress; import java.net.UnknownHostException; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.UUID; -import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.function.Supplier; -import java.util.function.UnaryOperator; import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import reactor.core.Disposable; import reactor.core.Disposables; import reactor.core.Exceptions; import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; import reactor.core.scheduler.Scheduler; import reactor.core.scheduler.Schedulers; @@ -114,283 +107,447 @@ * * } */ -public final class Microservices implements AutoCloseable { - - public static final Logger LOGGER = LoggerFactory.getLogger(Microservices.class); - - private final String id = UUID.randomUUID().toString(); - private final Map tags; - private final List serviceProviders; - private final ServiceRegistry serviceRegistry; - private final Authenticator defaultAuthenticator; - private final ServiceTransportBootstrap transportBootstrap; - private final GatewayBootstrap gatewayBootstrap; - private final ServiceDiscoveryBootstrap discoveryBootstrap; - private final ServiceProviderErrorMapper defaultErrorMapper; - private final ServiceMessageDataDecoder defaultDataDecoder; - private final String defaultContentType; - private final PrincipalMapper defaultPrincipalMapper; - private final Sinks.One shutdown = Sinks.one(); - private final Sinks.One onShutdown = Sinks.one(); +public class Microservices implements AutoCloseable { + + private static final Logger LOGGER = System.getLogger(Microservices.class.getName()); + + private final Microservices.Context context; + private final UUID id = UUID.randomUUID(); + private final String instanceId = Integer.toHexString(id.hashCode()); + + private ServiceTransport serviceTransport; + private ClientTransport clientTransport; + private ServerTransport serverTransport; + private Address serviceAddress = Address.NULL_ADDRESS; private ServiceEndpoint serviceEndpoint; - private final String externalHost; - private final Integer externalPort; - - private Microservices(Builder builder) { - this.tags = Collections.unmodifiableMap(new HashMap<>(builder.tags)); - this.serviceProviders = new ArrayList<>(builder.serviceProviders); - this.serviceRegistry = builder.serviceRegistry; - this.defaultAuthenticator = builder.defaultAuthenticator; - this.gatewayBootstrap = builder.gatewayBootstrap; - this.discoveryBootstrap = builder.discoveryBootstrap; - this.transportBootstrap = builder.transportBootstrap; - this.defaultErrorMapper = builder.defaultErrorMapper; - this.defaultDataDecoder = builder.defaultDataDecoder; - this.defaultContentType = builder.defaultContentType; - this.defaultPrincipalMapper = builder.defaultPrincipalMapper; - this.externalHost = builder.externalHost; - this.externalPort = builder.externalPort; - - // Setup cleanup - shutdown - .asMono() - .then(doShutdown()) - .doFinally(s -> onShutdown.emitEmpty(busyLooping(Duration.ofSeconds(3)))) - .subscribe( - null, ex -> LOGGER.warn("[{}][doShutdown] Exception occurred: {}", id, ex.toString())); + private ServiceCall serviceCall; + private List serviceInstances; + private final List gateways = new ArrayList<>(); + private ServiceDiscovery serviceDiscovery; + private final Sinks.Many discoverySink = + Sinks.many().multicast().directBestEffort(); + private final Disposable.Composite disposables = Disposables.composite(); + private Scheduler scheduler; + private Address discoveryAddress; + + private Microservices(Microservices.Context context) { + this.context = context; } - public static Builder builder() { - return new Builder(); + public static Microservices start(Microservices.Context context) { + final Microservices microservices = new Microservices(context.conclude()); + try { + LOGGER.log(Level.INFO, "[{0}] Starting {1}", microservices.instanceId, microservices); + microservices.startTransport(context.transportSupplier, context.serviceRegistry); + microservices.createServiceEndpoint(); + microservices.startGateways(); + microservices.createDiscovery(); + microservices.doInject(); + microservices.startListen(); + LOGGER.log(Level.INFO, "[{0}] Started {1}", microservices.instanceId, microservices); + } catch (Exception ex) { + microservices.close(); + throw Exceptions.propagate(ex); + } + return microservices; } - public String id() { - return this.id; + private void startTransport( + Supplier transportSupplier, ServiceRegistry serviceRegistry) { + if (transportSupplier == null) { + return; + } + + serviceTransport = transportSupplier.get().start(); + serverTransport = serviceTransport.serverTransport(serviceRegistry).bind(); + clientTransport = serviceTransport.clientTransport(); + serviceAddress = prepareAddress(serverTransport.address()); + + LOGGER.log( + Level.INFO, + "[{0}] Started {1}, serviceAddress: {2}", + instanceId, + serviceTransport, + serviceAddress); } - @Override - public String toString() { - return "Microservices@" + id; + private static Address prepareAddress(Address address) { + final InetAddress inetAddress; + try { + inetAddress = InetAddress.getByName(address.host()); + } catch (UnknownHostException e) { + throw Exceptions.propagate(e); + } + if (inetAddress.isAnyLocalAddress()) { + return Address.create(Address.getLocalIpAddress().getHostAddress(), address.port()); + } else { + return Address.create(inetAddress.getHostAddress(), address.port()); + } } - private Mono start() { - return Mono.fromCallable(() -> transportBootstrap.start(this)) - .flatMap( - transportBootstrap -> { - final ServiceCall serviceCall = call(); - final Address serviceAddress = transportBootstrap.transportAddress; - - final ServiceEndpoint.Builder serviceEndpointBuilder = - ServiceEndpoint.builder() - .id(id) - .address(serviceAddress) - .contentTypes(DataCodec.getAllContentTypes()) - .tags(tags); - - // invoke service providers and register services - final List serviceInstances = - serviceProviders.stream() - .flatMap(serviceProvider -> serviceProvider.provide(serviceCall).stream()) - .peek(this::registerService) - .peek( - serviceInfo -> - serviceEndpointBuilder.appendServiceRegistrations( - ServiceScanner.scanServiceInfo(serviceInfo))) - .map(ServiceInfo::serviceInstance) - .collect(Collectors.toList()); - - serviceEndpoint = newServiceEndpoint(serviceEndpointBuilder.build()); - - return concludeDiscovery( - this, new ServiceDiscoveryOptions().serviceEndpoint(serviceEndpoint)) - .then(startGateway(new GatewayOptions().call(serviceCall))) - .then(Mono.fromCallable(() -> Injector.inject(this, serviceInstances))) - .then(discoveryBootstrap.startListen()) - .thenReturn(this); - }) - .doOnSubscribe(s -> LOGGER.info("[{}][start] Starting", id)) - .doOnSuccess(m -> LOGGER.info("[{}][start] Started", id)) - .onErrorResume(ex -> Mono.defer(this::shutdown).then(Mono.error(ex))); + private void createServiceEndpoint() { + serviceCall = call(); + + final ServiceEndpoint.Builder builder = + ServiceEndpoint.builder() + .id(id.toString()) + .address(serviceAddress) + .contentTypes(DataCodec.getAllContentTypes()) + .tags(context.tags); + + serviceInstances = + context.serviceProviders.stream() + .flatMap(serviceProvider -> serviceProvider.provide(serviceCall).stream()) + .peek(this::registerService) + .peek( + serviceInfo -> + builder.appendServiceRegistrations(ServiceScanner.scanServiceInfo(serviceInfo))) + .map(ServiceInfo::serviceInstance) + .collect(Collectors.toList()); + + serviceEndpoint = newServiceEndpoint(builder.build()); + + LOGGER.log( + Level.INFO, + "[{0}] Created serviceEndpoint: {1}, serviceInstances: {2}", + instanceId, + serviceEndpoint, + serviceInstances); } private ServiceEndpoint newServiceEndpoint(ServiceEndpoint serviceEndpoint) { final ServiceEndpoint.Builder builder = ServiceEndpoint.from(serviceEndpoint); final String finalHost = - Optional.ofNullable(externalHost).orElse(serviceEndpoint.address().host()); + Optional.ofNullable(context.externalHost).orElse(serviceEndpoint.address().host()); final int finalPort = - Optional.ofNullable(externalPort).orElse(serviceEndpoint.address().port()); + Optional.ofNullable(context.externalPort).orElse(serviceEndpoint.address().port()); return builder.address(Address.create(finalHost, finalPort)).build(); } - private Mono startGateway(GatewayOptions options) { - return Mono.fromCallable(() -> gatewayBootstrap.start(this, options)); + private void registerService(ServiceInfo serviceInfo) { + context.serviceRegistry.registerService( + ServiceInfo.from(serviceInfo) + .errorMapperIfAbsent(context.defaultErrorMapper) + .dataDecoderIfAbsent(context.defaultDataDecoder) + .authenticatorIfAbsent(context.defaultAuthenticator) + .principalMapperIfAbsent(context.defaultPrincipalMapper) + .build()); + } + + private void startGateways() { + final GatewayOptions options = new GatewayOptions().call(serviceCall); + for (Function factory : context.gatewayFactories) { + final var gateway = factory.apply(options); + final var finalGateway = gateway.start(); + gateways.add(finalGateway); + LOGGER.log( + Level.INFO, + "[{0}] Started {1}, gateway: {2}@{3}", + instanceId, + finalGateway, + finalGateway.id(), + finalGateway.address()); + } } - private Mono concludeDiscovery( - Microservices microservices, ServiceDiscoveryOptions options) { - return Mono.fromCallable(() -> discoveryBootstrap.conclude(microservices, options)); + private void createDiscovery() { + scheduler = Schedulers.newSingle("discovery", true); + + final ServiceDiscoveryFactory discoveryFactory = context.discoveryFactory; + if (discoveryFactory == null) { + return; + } + + serviceDiscovery = discoveryFactory.createServiceDiscovery(serviceEndpoint); + + LOGGER.log(Level.INFO, "[0] Created {1}", instanceId, serviceDiscovery); } - private void registerService(ServiceInfo serviceInfo) { - serviceRegistry.registerService( - ServiceInfo.from(serviceInfo) - .errorMapperIfAbsent(defaultErrorMapper) - .dataDecoderIfAbsent(defaultDataDecoder) - .authenticatorIfAbsent(defaultAuthenticator) - .principalMapperIfAbsent(defaultPrincipalMapper) - .build()); + private void doInject() { + Injector.inject(this, serviceInstances); + } + + private void startListen() { + if (serviceDiscovery == null) { + return; + } + + disposables.add( + serviceDiscovery + .listen() + .subscribeOn(scheduler) + .publishOn(scheduler) + .doOnNext(this::onDiscoveryEvent) + .doOnNext(event -> discoverySink.emitNext(event, busyLooping(Duration.ofSeconds(3)))) + .doOnError(ex -> LOGGER.log(Level.ERROR, "[{0}] Exception occurred", instanceId, ex)) + .subscribe()); + + serviceDiscovery.start(); + discoveryAddress = serviceDiscovery.address(); + + LOGGER.log( + Level.INFO, + "[{0}] Started {1}, discoveryAddress: {2}", + instanceId, + serviceDiscovery, + discoveryAddress); } + private void onDiscoveryEvent(ServiceDiscoveryEvent event) { + final ServiceRegistry serviceRegistry = context.serviceRegistry; + + if (event.isEndpointAdded()) { + serviceRegistry.registerService(event.serviceEndpoint()); + } + + if (event.isEndpointLeaving() || event.isEndpointRemoved()) { + serviceRegistry.unregisterService(event.serviceEndpoint().id()); + } + } + + /** + * Returns listening address of the {@link ServerTransport}. + * + * @return address, or null (if {@link ServiceTransport} was not specified) + */ public Address serviceAddress() { - return transportBootstrap.transportAddress; + return serviceAddress; } + /** + * Returns new instance of {@link ServiceCall}. + * + * @return new instance of {@link ServiceCall} + */ public ServiceCall call() { return new ServiceCall() - .transport(transportBootstrap.clientTransport) - .serviceRegistry(serviceRegistry) - .contentType(defaultContentType) - .errorMapper(DefaultErrorMapper.INSTANCE) + .transport(clientTransport) + .serviceRegistry(context.serviceRegistry) .router(Routers.getRouter(RoundRobinServiceRouter.class)); } + /** + * Returns started gateway instances. Returned list can be empty, if {@link #gateway(String)} was + * not called. + * + * @return list {@link Gateway} objects, or empty list, if gateways were not specified + */ public List gateways() { - return gatewayBootstrap.gateways(); + return gateways; } + /** + * Returns gateway by id. + * + * @param id gateway id + * @return {@link Gateway} instance, or throwing exception if gateway cannot be found + */ public Gateway gateway(String id) { - return gatewayBootstrap.gateway(id); + return gateways.stream() + .filter(gateway -> gateway.id().equals(id)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Cannot find gateway by id=" + id)); } + /** + * Returns local {@link ServiceEndpoint} object. + * + * @return local {@link ServiceEndpoint} object + */ public ServiceEndpoint serviceEndpoint() { return serviceEndpoint; } + /** + * Returns list of {@link ServiceEndpoint} objects. Service endpoints being landed into {@link + * Microservices} instance through the {@link ServiceRegistry#registerService(ServiceEndpoint)}, + * which by turn is called by listening and handling service discovery events. + * + * @return service endpoints + */ public List serviceEndpoints() { - return serviceRegistry.listServiceEndpoints(); + return context.serviceRegistry.listServiceEndpoints(); } + /** + * Returns service tags. + * + * @return service tags. + */ public Map tags() { - return tags; - } - - public ServiceRegistry serviceRegistry() { - return serviceRegistry; - } - - public Address discoveryAddress() { - return discoveryBootstrap.serviceDiscovery != null - ? discoveryBootstrap.serviceDiscovery.address() - : null; + return context.tags; } /** - * Function to subscribe and listen on the stream of {@code ServiceDiscoveryEvent}\s from - * composite service discovery instance. - * - *

Can be called before or after composite service discovery {@code .start()} method call (i.e - * before of after all service discovery instances will be started). If it's called before then - * new events will be streamed from all service discovery instances, if it's called after then - * {@link ServiceRegistry#listServiceEndpoints()} will be turned to service discovery events of - * type {@link Type#ENDPOINT_ADDED}, and concateneted with a stream of live events. + * Returns {@link ServiceRegistry}. * - * @return stream of {@code ServiceDiscoveryEvent}\s + * @return service registry */ - public Flux listenDiscovery() { - return discoveryBootstrap.listen(); + public ServiceRegistry serviceRegistry() { + return context.serviceRegistry; } /** - * Shutdown instance and clear resources. + * Returns listening address of the {@link ServiceDiscovery}. * - * @return result of shutdown + * @return address, or null (if {@link ServiceDiscovery} was not specified) */ - public Mono shutdown() { - return Mono.defer( - () -> { - shutdown.emitEmpty(busyLooping(Duration.ofSeconds(3))); - return onShutdown.asMono(); - }); + public Address discoveryAddress() { + return discoveryAddress; } /** - * Returns signal of when shutdown was completed. + * Function to subscribe and listen on the stream of {@link ServiceDiscoveryEvent} objects from + * {@link ServiceDiscovery} instance. * - * @return signal of when shutdown completed + * @return stream of {@link ServiceDiscoveryEvent} objects */ - public Mono onShutdown() { - return onShutdown.asMono(); + public Flux listenDiscovery() { + return Flux.fromStream(context.serviceRegistry.listServiceEndpoints().stream()) + .map(ServiceDiscoveryEvent::newEndpointAdded) + .concatWith(discoverySink.asFlux().onBackpressureBuffer()) + .subscribeOn(scheduler) + .publishOn(scheduler); } - private Mono doShutdown() { - return Mono.whenDelayError( - applyBeforeDestroy(), - Mono.fromRunnable(discoveryBootstrap::close), - Mono.fromRunnable(gatewayBootstrap::close), - Mono.fromRunnable(transportBootstrap::close)) - .doOnSubscribe(s -> LOGGER.info("[{}][doShutdown] Shutting down", id)) - .doOnSuccess(s -> LOGGER.info("[{}][doShutdown] Shutdown", id)); + @Override + public void close() { + LOGGER.log(Level.INFO, "[{0}] Closing {1} ...", instanceId, this); + processBeforeDestroy(); + closeDiscovery(); + closeGateways(); + closeTransport(); + LOGGER.log(Level.INFO, "[{0}] Closed {1}", instanceId, this); } - private Mono applyBeforeDestroy() { - return Mono.defer( - () -> - Mono.whenDelayError( - serviceRegistry.listServices().stream() - .map(ServiceInfo::serviceInstance) - .map(s -> Mono.fromRunnable(() -> Injector.processBeforeDestroy(this, s))) - .collect(Collectors.toList()))); + private void processBeforeDestroy() { + context + .serviceRegistry + .listServices() + .forEach( + serviceInfo -> { + try { + Injector.processBeforeDestroy(this, serviceInfo.serviceInstance()); + } catch (Exception e) { + LOGGER.log( + Level.ERROR, + "[{0}][processBeforeDestroy] Exception occurred: {1}", + instanceId, + e.toString()); + } + }); } - @Override - public void close() { - try { - shutdown().toFuture().get(); - } catch (Exception e) { - throw new RuntimeException(e); + private void closeTransport() { + if (clientTransport != null) { + try { + clientTransport.close(); + } catch (Exception e) { + LOGGER.log( + Level.ERROR, + "[{0}][clientTransport.close] Exception occurred: {1}", + instanceId, + e.toString()); + } + } + + if (serverTransport != null) { + try { + serverTransport.stop(); + } catch (Exception e) { + LOGGER.log( + Level.ERROR, + "[{0}][serverTransport.close] Exception occurred: {1}", + instanceId, + e.toString()); + } + } + + if (serviceTransport != null) { + try { + serviceTransport.stop(); + } catch (Exception e) { + LOGGER.log( + Level.ERROR, + "[{0}][serviceTransport.stop] Exception occurred: {1}", + instanceId, + e.toString()); + } } } - public static final class Builder { - - private Map tags = new HashMap<>(); - private final List serviceProviders = new ArrayList<>(); - private ServiceRegistry serviceRegistry = new ServiceRegistryImpl(); - private Authenticator defaultAuthenticator = null; - private final ServiceDiscoveryBootstrap discoveryBootstrap = new ServiceDiscoveryBootstrap(); - private ServiceTransportBootstrap transportBootstrap = new ServiceTransportBootstrap(); - private final GatewayBootstrap gatewayBootstrap = new GatewayBootstrap(); - private ServiceProviderErrorMapper defaultErrorMapper = DefaultErrorMapper.INSTANCE; - private ServiceMessageDataDecoder defaultDataDecoder = - Optional.ofNullable(ServiceMessageDataDecoder.INSTANCE) - .orElse((message, dataType) -> message); - private String defaultContentType = ServiceMessage.DEFAULT_DATA_FORMAT; - private PrincipalMapper defaultPrincipalMapper = null; - private String externalHost; - private Integer externalPort; + private void closeGateways() { + gateways.forEach( + gateway -> { + try { + gateway.stop(); + } catch (Exception e) { + LOGGER.log( + Level.ERROR, + "[{0}][gateway.stop] Exception occurred: {1}", + instanceId, + e.toString()); + } + }); + } + + private void closeDiscovery() { + disposables.dispose(); - public Mono start() { - return Mono.defer(() -> new Microservices(this).start()); + if (serviceDiscovery != null) { + try { + serviceDiscovery.shutdown(); + } catch (Exception e) { + LOGGER.log( + Level.ERROR, "[{0}][closeDiscovery] Exception occurred: {1}", instanceId, e.toString()); + } } - public Microservices startAwait() { - return start().block(); + if (scheduler != null) { + scheduler.dispose(); } + } + + public static final class Context { + + private final AtomicBoolean isConcluded = new AtomicBoolean(); + + private Map tags; + private List serviceProviders = new ArrayList<>(); + private ServiceRegistry serviceRegistry; + private Authenticator defaultAuthenticator; + private PrincipalMapper defaultPrincipalMapper; + private ServiceProviderErrorMapper defaultErrorMapper; + private ServiceMessageDataDecoder defaultDataDecoder; + private String externalHost; + private Integer externalPort; + private ServiceDiscoveryFactory discoveryFactory; + private Supplier transportSupplier; + private List> gatewayFactories = new ArrayList<>(); + + public Context() {} - public Builder services(ServiceInfo... services) { + /** + * Setter for services. + * + * @param services {@link ServiceInfo} objects + * @return this + */ + public Context services(ServiceInfo... services) { serviceProviders.add(call -> Arrays.stream(services).collect(Collectors.toList())); return this; } /** - * Adds service instance to microservice. + * Setter for services. All services that are not instance of {@link ServiceInfo} will be + * wrapped into {@link ServiceInfo}. * - * @param services service instance. - * @return builder + * @param services services + * @return this */ - public Builder services(Object... services) { + public Context services(Object... services) { serviceProviders.add( call -> Arrays.stream(services) @@ -403,43 +560,93 @@ public Builder services(Object... services) { return this; } - public Builder services(ServiceProvider serviceProvider) { + /** + * Setter for {@link ServiceProvider}. + * + * @param serviceProvider serviceProvider + * @return this + */ + public Context services(ServiceProvider serviceProvider) { serviceProviders.add(serviceProvider); return this; } - public Builder externalHost(String externalHost) { + /** + * Setter for externalHost. If specified, this host will be assgined to the host of the {@link + * ServiceEndpoint#address()}. + * + * @param externalHost externalHost + * @return this + */ + public Context externalHost(String externalHost) { this.externalHost = externalHost; return this; } - public Builder externalPort(Integer externalPort) { + /** + * Setter for externalPort. If specified, this port will be assgined to the port of the {@link + * ServiceEndpoint#address()}. + * + * @param externalPort externalPort + * @return this + */ + public Context externalPort(Integer externalPort) { this.externalPort = externalPort; return this; } - public Builder serviceRegistry(ServiceRegistry serviceRegistry) { - this.serviceRegistry = serviceRegistry; + /** + * Setter for tags. + * + * @param tags tags + * @return this + */ + public Context tags(Map tags) { + this.tags = tags; return this; } - public Builder discovery(ServiceDiscoveryFactory discoveryFactory) { - this.discoveryBootstrap.operator(options -> options.discoveryFactory(discoveryFactory)); + /** + * Setter for {@link ServiceRegistry}. + * + * @param serviceRegistry serviceRegistry + * @return this + */ + public Context serviceRegistry(ServiceRegistry serviceRegistry) { + this.serviceRegistry = serviceRegistry; return this; } - public Builder transport(Supplier supplier) { - this.transportBootstrap = new ServiceTransportBootstrap(supplier); + /** + * Setter for {@link ServiceDiscoveryFactory}. + * + * @param discoveryFactory discoveryFactory + * @return this + */ + public Context discovery(ServiceDiscoveryFactory discoveryFactory) { + this.discoveryFactory = discoveryFactory; return this; } - public Builder tags(Map tags) { - this.tags = tags; + /** + * Setter for supplier of {@link ServiceTransport} instance. + * + * @param transportSupplier supplier of {@link ServiceTransport} instance + * @return this + */ + public Context transport(Supplier transportSupplier) { + this.transportSupplier = transportSupplier; return this; } - public Builder gateway(Function factory) { - gatewayBootstrap.addFactory(factory); + /** + * Setter for gateway. + * + * @param factory gateway factory + * @return this + */ + public Context gateway(Function factory) { + gatewayFactories.add(factory); return this; } @@ -450,8 +657,8 @@ public Builder gateway(Function factory) { * @param errorMapper error mapper; not null * @return this builder with applied parameter */ - public Builder defaultErrorMapper(ServiceProviderErrorMapper errorMapper) { - this.defaultErrorMapper = Objects.requireNonNull(errorMapper, "default errorMapper"); + public Context defaultErrorMapper(ServiceProviderErrorMapper errorMapper) { + this.defaultErrorMapper = errorMapper; return this; } @@ -463,20 +670,8 @@ public Builder defaultErrorMapper(ServiceProviderErrorMapper errorMapper) { * @param dataDecoder data decoder; not null * @return this builder with applied parameter */ - public Builder defaultDataDecoder(ServiceMessageDataDecoder dataDecoder) { - this.defaultDataDecoder = Objects.requireNonNull(dataDecoder, "default dataDecoder"); - return this; - } - - /** - * Setter for default {@code contentType}. By default, default {@code contentType} is set to - * {@link ServiceMessage#DEFAULT_DATA_FORMAT}. - * - * @param contentType contentType; not null - * @return this builder with applied parameter - */ - public Builder defaultContentType(String contentType) { - this.defaultContentType = Objects.requireNonNull(contentType, "default contentType"); + public Context defaultDataDecoder(ServiceMessageDataDecoder dataDecoder) { + this.defaultDataDecoder = dataDecoder; return this; } @@ -486,7 +681,7 @@ public Builder defaultContentType(String contentType) { * @param authenticator authenticator; optional * @return this builder with applied parameter */ - public Builder defaultAuthenticator(Authenticator authenticator) { + public Context defaultAuthenticator(Authenticator authenticator) { //noinspection unchecked this.defaultAuthenticator = (Authenticator) authenticator; return this; @@ -501,261 +696,45 @@ public Builder defaultAuthenticator(Authenticator authenticator * @param principal type * @return this builder with applied parameter */ - public Builder defaultPrincipalMapper( + public Context defaultPrincipalMapper( PrincipalMapper principalMapper) { //noinspection unchecked this.defaultPrincipalMapper = (PrincipalMapper) principalMapper; return this; } - } - - private static class ServiceDiscoveryBootstrap implements AutoCloseable { - - private UnaryOperator operator; - private ServiceDiscovery serviceDiscovery; - - // Sink - private final Sinks.Many sink = - Sinks.many().multicast().directBestEffort(); - - private final Disposable.Composite disposables = Disposables.composite(); - private Scheduler scheduler; - private Microservices microservices; - - private ServiceDiscoveryBootstrap() {} - - private ServiceDiscoveryBootstrap operator(UnaryOperator op) { - operator = op; - return this; - } - - private ServiceDiscoveryBootstrap conclude( - Microservices microservices, ServiceDiscoveryOptions options) { - this.microservices = microservices; - this.scheduler = Schedulers.newSingle("discovery", true); - - if (operator == null) { - return this; - } - - options = operator.apply(options); - final ServiceEndpoint serviceEndpoint = options.serviceEndpoint(); - final ServiceDiscoveryFactory discoveryFactory = options.discoveryFactory(); - - if (discoveryFactory == null) { - return this; - } - - serviceDiscovery = discoveryFactory.createServiceDiscovery(serviceEndpoint); - - return this; - } - - private Mono startListen() { - return Mono.defer( - () -> { - if (serviceDiscovery == null) { - return Mono.empty(); - } - - disposables.add( - serviceDiscovery - .listen() - .subscribeOn(scheduler) - .publishOn(scheduler) - .doOnNext(event -> onDiscoveryEvent(microservices, event)) - .doOnNext(event -> sink.emitNext(event, busyLooping(Duration.ofSeconds(3)))) - .subscribe()); - - return Mono.fromRunnable(serviceDiscovery::start) - .then() - .doOnSubscribe(s -> LOGGER.info("[{}][startListen] Starting", microservices.id())) - .doOnSuccess(avoid -> LOGGER.info("[{}][startListen] Started", microservices.id())) - .doOnError( - ex -> - LOGGER.error( - "[{}][startListen] Exception occurred: {}", - microservices.id(), - ex.toString())); - }); - } - public Flux listen() { - return Flux.fromStream(microservices.serviceRegistry.listServiceEndpoints().stream()) - .map(ServiceDiscoveryEvent::newEndpointAdded) - .concatWith(sink.asFlux().onBackpressureBuffer()) - .subscribeOn(scheduler) - .publishOn(scheduler); - } - - private void onDiscoveryEvent(Microservices microservices, ServiceDiscoveryEvent event) { - if (event.isEndpointAdded()) { - microservices.serviceRegistry.registerService(event.serviceEndpoint()); - } - if (event.isEndpointLeaving() || event.isEndpointRemoved()) { - microservices.serviceRegistry.unregisterService(event.serviceEndpoint().id()); + private Context conclude() { + if (!isConcluded.compareAndSet(false, true)) { + throw new IllegalStateException("Context is already concluded"); } - } - - @Override - public void close() { - disposables.dispose(); - - sink.emitComplete(busyLooping(Duration.ofSeconds(3))); - try { - if (serviceDiscovery != null) { - serviceDiscovery.shutdown(); - } - } finally { - if (scheduler != null) { - scheduler.dispose(); - } - } - } - } - - private static class GatewayBootstrap implements AutoCloseable { - - private final List> factories = new ArrayList<>(); - private final List gateways = new CopyOnWriteArrayList<>(); - - private GatewayBootstrap addFactory(Function factory) { - this.factories.add(factory); - return this; - } - - private GatewayBootstrap start(Microservices microservices, GatewayOptions options) { - for (Function factory : factories) { - LOGGER.info("[{}][gateway][{}][start] Starting", microservices.id(), options.id()); - - try { - final Gateway gateway = factory.apply(options).start().toFuture().get(); - - gateways.add(gateway); - - LOGGER.info( - "[{}][gateway][{}][start] Started, address: {}", - microservices.id(), - gateway.id(), - gateway.address()); - } catch (Exception ex) { - LOGGER.error( - "[{}][gateway][{}][start] Exception occurred: {}", - microservices.id(), - options.id(), - ex.toString()); - throw new RuntimeException(ex); - } + if (defaultErrorMapper == null) { + defaultErrorMapper = DefaultErrorMapper.INSTANCE; } - return this; - } - - private List gateways() { - return new ArrayList<>(gateways); - } - - private Gateway gateway(String id) { - return gateways.stream() - .filter(gateway -> gateway.id().equals(id)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Cannot find gateway by id=" + id)); - } - - @Override - public void close() { - try { - Mono.whenDelayError(gateways.stream().map(Gateway::stop).toArray(Mono[]::new)) - .toFuture() - .get(); - } catch (Exception e) { - throw new RuntimeException(e); + if (defaultDataDecoder == null) { + defaultDataDecoder = + Optional.ofNullable(ServiceMessageDataDecoder.INSTANCE) + .orElse((message, dataType) -> message); } - } - } - - private static class ServiceTransportBootstrap implements AutoCloseable { - private final Supplier transportSupplier; - - private ServiceTransport serviceTransport; - private ClientTransport clientTransport; - private ServerTransport serverTransport; - private Address transportAddress = Address.NULL_ADDRESS; - - private ServiceTransportBootstrap() { - this(null); - } - - private ServiceTransportBootstrap(Supplier transportSupplier) { - this.transportSupplier = transportSupplier; - } - - private ServiceTransportBootstrap start(Microservices microservices) { - if (transportSupplier == null || (serviceTransport = transportSupplier.get()) == null) { - return this; + if (serviceRegistry == null) { + serviceRegistry = new ServiceRegistryImpl(); } - LOGGER.info("[{}][serviceTransport][start] Starting", microservices.id()); - - try { - try { - serviceTransport = serviceTransport.start(); - serverTransport = serviceTransport.serverTransport(microservices.serviceRegistry).bind(); - } catch (Exception e) { - throw new RuntimeException(e); - } - - transportAddress = prepareAddress(serverTransport.address()); - clientTransport = serviceTransport.clientTransport(); - - LOGGER.info( - "[{}][serviceTransport][start] Started, address: {}", - microservices.id(), - serverTransport.address()); - - return this; - } catch (Exception ex) { - LOGGER.error( - "[{}][serviceTransport][start] Exception occurred: {}", - microservices.id(), - ex.toString()); - throw new RuntimeException(ex); + if (tags == null) { + tags = new HashMap<>(); } - } - private static Address prepareAddress(Address address) { - final InetAddress inetAddress; - try { - inetAddress = InetAddress.getByName(address.host()); - } catch (UnknownHostException e) { - throw Exceptions.propagate(e); - } - if (inetAddress.isAnyLocalAddress()) { - return Address.create(Address.getLocalIpAddress().getHostAddress(), address.port()); - } else { - return Address.create(inetAddress.getHostAddress(), address.port()); + if (serviceProviders == null) { + serviceProviders = new ArrayList<>(); } - } - @Override - public void close() { - if (serverTransport != null) { - try { - serverTransport.stop(); - } catch (Exception e) { - LOGGER.warn("[serverTransport][stop] Exception: {}", e.toString()); - } + if (gatewayFactories == null) { + gatewayFactories = new ArrayList<>(); } - if (serviceTransport != null) { - try { - serviceTransport.stop(); - } catch (Exception e) { - LOGGER.warn("[serviceTransport][stop] Exception: {}", e.toString()); - } - } + return this; } } } diff --git a/services/src/main/java/io/scalecube/services/registry/ServiceRegistryImpl.java b/services/src/main/java/io/scalecube/services/registry/ServiceRegistryImpl.java index 7619703f9..db2bc3c64 100644 --- a/services/src/main/java/io/scalecube/services/registry/ServiceRegistryImpl.java +++ b/services/src/main/java/io/scalecube/services/registry/ServiceRegistryImpl.java @@ -8,6 +8,8 @@ import io.scalecube.services.methods.MethodInfo; import io.scalecube.services.methods.ServiceMethodInvoker; import io.scalecube.services.registry.api.ServiceRegistry; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -19,12 +21,10 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; import org.jctools.maps.NonBlockingHashMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class ServiceRegistryImpl implements ServiceRegistry { - private static final Logger LOGGER = LoggerFactory.getLogger(ServiceRegistryImpl.class); + private static final Logger LOGGER = System.getLogger(ServiceRegistryImpl.class.getName()); // todo how to remove it (tags problem)? private final Map serviceEndpoints = new NonBlockingHashMap<>(); @@ -65,7 +65,7 @@ public List lookupService(ServiceMessage request) { public boolean registerService(ServiceEndpoint serviceEndpoint) { boolean success = serviceEndpoints.putIfAbsent(serviceEndpoint.id(), serviceEndpoint) == null; if (success) { - LOGGER.debug("ServiceEndpoint registered: {}", serviceEndpoint); + LOGGER.log(Level.DEBUG, "ServiceEndpoint registered: {0}", serviceEndpoint); serviceEndpoint .serviceReferences() .forEach( @@ -81,7 +81,7 @@ public boolean registerService(ServiceEndpoint serviceEndpoint) { public ServiceEndpoint unregisterService(String endpointId) { ServiceEndpoint serviceEndpoint = serviceEndpoints.remove(endpointId); if (serviceEndpoint != null) { - LOGGER.debug("ServiceEndpoint unregistered: {}", serviceEndpoint); + LOGGER.log(Level.DEBUG, "ServiceEndpoint unregistered: {0}", serviceEndpoint); List serviceReferencesOfEndpoint = serviceReferencesByQualifier.values().stream() @@ -144,7 +144,7 @@ public void registerService(ServiceInfo serviceInfo) { private void checkMethodInvokerDoesntExist(MethodInfo methodInfo) { if (methodInvokers.containsKey(methodInfo.qualifier()) || methodInvokers.containsKey(methodInfo.oldQualifier())) { - LOGGER.error("MethodInvoker already exists, methodInfo: {}", methodInfo); + LOGGER.log(Level.ERROR, "MethodInvoker already exists, methodInfo: {0}", methodInfo); throw new IllegalStateException("MethodInvoker already exists"); } } diff --git a/services/src/test/java/io/scalecube/services/ErrorFlowTest.java b/services/src/test/java/io/scalecube/services/ErrorFlowTest.java index 7189e2174..272248d8d 100644 --- a/services/src/test/java/io/scalecube/services/ErrorFlowTest.java +++ b/services/src/test/java/io/scalecube/services/ErrorFlowTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static reactor.core.publisher.Mono.from; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.exceptions.BadRequestException; @@ -30,28 +31,29 @@ public class ErrorFlowTest extends BaseTest { @BeforeAll public static void initNodes() throws InterruptedException { provider = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .transport(cfg -> cfg.port(PORT.incrementAndGet())) - .options(opts -> opts.metadata(endpoint))) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .transport(cfg -> cfg.port(PORT.incrementAndGet())) + .options(opts -> opts.metadata(endpoint))) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); consumer = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .membership(cfg -> cfg.seedMembers(provider.discoveryAddress().toString())) - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .transport(cfg -> cfg.port(PORT.incrementAndGet())) - .options(opts -> opts.metadata(endpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .membership( + cfg -> cfg.seedMembers(provider.discoveryAddress().toString())) + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .transport(cfg -> cfg.port(PORT.incrementAndGet())) + .options(opts -> opts.metadata(endpoint))) + .transport(RSocketServiceTransport::new)); while (consumer.serviceEndpoints().size() != 1) { //noinspection BusyWait @@ -61,8 +63,8 @@ public static void initNodes() throws InterruptedException { @AfterAll public static void shutdownNodes() { - consumer.shutdown().block(); - provider.shutdown().block(); + consumer.close(); + provider.close(); } @Test diff --git a/services/src/test/java/io/scalecube/services/ServiceAuthRemoteTest.java b/services/src/test/java/io/scalecube/services/ServiceAuthRemoteTest.java index 3bcae7948..d7db334b3 100644 --- a/services/src/test/java/io/scalecube/services/ServiceAuthRemoteTest.java +++ b/services/src/test/java/io/scalecube/services/ServiceAuthRemoteTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import io.rsocket.exceptions.RejectedSetupException; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.auth.Authenticator; import io.scalecube.services.auth.PrincipalMapper; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; @@ -75,60 +76,60 @@ static void beforeAll() { principalMapper = authData -> new UserProfile(authData.get("name"), authData.get("role")); service = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(() -> new RSocketServiceTransport().authenticator(authenticator)) - .services( - ServiceInfo.fromServiceInstance(new SecuredServiceImpl()) - .principalMapper(principalMapper) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(() -> new RSocketServiceTransport().authenticator(authenticator)) + .services( + ServiceInfo.fromServiceInstance(new SecuredServiceImpl()) + .principalMapper(principalMapper) + .build())); serviceWithoutAuthenticator = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .services( - ServiceInfo.fromServiceInstance(new AnotherSecuredServiceImpl()) - .principalMapper(principalMapper) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .services( + ServiceInfo.fromServiceInstance(new AnotherSecuredServiceImpl()) + .principalMapper(principalMapper) + .build())); partiallySecuredService = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(() -> new RSocketServiceTransport().authenticator(authenticator)) - .services( - ServiceInfo.fromServiceInstance(new PartiallySecuredServiceImpl()) - .principalMapper(principalMapper) - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(() -> new RSocketServiceTransport().authenticator(authenticator)) + .services( + ServiceInfo.fromServiceInstance(new PartiallySecuredServiceImpl()) + .principalMapper(principalMapper) + .build())); } @AfterAll static void afterAll() { if (service != null) { - service.shutdown().block(TIMEOUT); + service.close(); } if (serviceWithoutAuthenticator != null) { - serviceWithoutAuthenticator.shutdown().block(TIMEOUT); + serviceWithoutAuthenticator.close(); } if (partiallySecuredService != null) { - partiallySecuredService.shutdown().block(TIMEOUT); + partiallySecuredService.close(); } } @@ -263,30 +264,30 @@ void successfulCallOfPublicMethodWithoutAuthentication() { } private static Microservices newCaller() { - return Microservices.builder() - .discovery(ServiceAuthRemoteTest::serviceDiscovery) - .transport( - () -> - new RSocketServiceTransport() - .credentialsSupplier(ServiceAuthRemoteTest::credentialsSupplier)) - .startAwait(); + return Microservices.start( + new Context() + .discovery(ServiceAuthRemoteTest::serviceDiscovery) + .transport( + () -> + new RSocketServiceTransport() + .credentialsSupplier(ServiceAuthRemoteTest::credentialsSupplier))); } private static Microservices newEmptyCredentialsCaller() { - return Microservices.builder() - .discovery(ServiceAuthRemoteTest::serviceDiscovery) - .transport(RSocketServiceTransport::new) - .startAwait(); + return Microservices.start( + new Context() + .discovery(ServiceAuthRemoteTest::serviceDiscovery) + .transport(RSocketServiceTransport::new)); } private static Microservices newInvalidCredentialsCaller() { - return Microservices.builder() - .discovery(ServiceAuthRemoteTest::serviceDiscovery) - .transport( - () -> - new RSocketServiceTransport() - .credentialsSupplier(ServiceAuthRemoteTest::invalidCredentialsSupplier)) - .startAwait(); + return Microservices.start( + new Context() + .discovery(ServiceAuthRemoteTest::serviceDiscovery) + .transport( + () -> + new RSocketServiceTransport() + .credentialsSupplier(ServiceAuthRemoteTest::invalidCredentialsSupplier))); } private static Mono> credentialsSupplier(ServiceReference serviceReference) { diff --git a/services/src/test/java/io/scalecube/services/ServiceCallLocalTest.java b/services/src/test/java/io/scalecube/services/ServiceCallLocalTest.java index be400b5c6..e836e8f07 100644 --- a/services/src/test/java/io/scalecube/services/ServiceCallLocalTest.java +++ b/services/src/test/java/io/scalecube/services/ServiceCallLocalTest.java @@ -16,6 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.exceptions.ServiceException; @@ -55,7 +56,7 @@ public static void setup() { @AfterAll public static void tearDown() { - provider.shutdown().block(); + provider.close(); } @Test @@ -73,15 +74,15 @@ public void test_local_async_no_params() { } private static Microservices serviceProvider() { - return Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + return Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); } @Test @@ -147,7 +148,7 @@ public void test_local_greeting_request_timeout_expires() { Publisher future = service.requestOne(GREETING_REQUEST_TIMEOUT_REQ); Throwable exception = - assertThrows(RuntimeException.class, () -> Mono.from(future).block(Duration.ofSeconds(1))); + assertThrows(RuntimeException.class, () -> Mono.from(future).block(Duration.ofMillis(500))); assertTrue(exception.getMessage().contains("Timeout on blocking read")); } diff --git a/services/src/test/java/io/scalecube/services/ServiceCallRemoteTest.java b/services/src/test/java/io/scalecube/services/ServiceCallRemoteTest.java index 55563b1af..e168c82a4 100644 --- a/services/src/test/java/io/scalecube/services/ServiceCallRemoteTest.java +++ b/services/src/test/java/io/scalecube/services/ServiceCallRemoteTest.java @@ -17,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.exceptions.ServiceException; @@ -60,29 +61,29 @@ public static void setup() { @AfterAll public static void tearDown() { try { - gateway.shutdown().block(); + gateway.close(); } catch (Exception ignore) { // no-op } try { - provider.shutdown().block(); + provider.close(); } catch (Exception ignore) { // no-op } } private static Microservices serviceProvider(Object service) { - return Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gateway.discoveryAddress().toString()))) - .transport(RSocketServiceTransport::new) - .services(service) - .startAwait(); + return Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gateway.discoveryAddress().toString()))) + .transport(RSocketServiceTransport::new) + .services(service)); } @Test @@ -188,7 +189,7 @@ public void test_remote_greeting_request_timeout_expires() { // call the service. Publisher future = service.requestOne(GREETING_REQUEST_TIMEOUT_REQ); Throwable exception = - assertThrows(RuntimeException.class, () -> Mono.from(future).block(Duration.ofSeconds(1))); + assertThrows(RuntimeException.class, () -> Mono.from(future).block(Duration.ofMillis(500))); assertTrue(exception.getMessage().contains("Timeout on blocking read")); } @@ -241,7 +242,7 @@ public void test_service_address_lookup_occur_only_after_subscription() { StepVerifier.create(quotes.take(1)).expectNextCount(1).expectComplete().verify(TIMEOUT); try { - quotesService.shutdown(); + quotesService.close(); } catch (Exception ignored) { // no-op } @@ -299,13 +300,13 @@ private static Optional route( } private static Microservices gateway() { - return Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + return Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); } } diff --git a/services/src/test/java/io/scalecube/services/ServiceDiscoverySubscriberTest.java b/services/src/test/java/io/scalecube/services/ServiceDiscoverySubscriberTest.java index 92e02b898..2c834af3b 100644 --- a/services/src/test/java/io/scalecube/services/ServiceDiscoverySubscriberTest.java +++ b/services/src/test/java/io/scalecube/services/ServiceDiscoverySubscriberTest.java @@ -4,6 +4,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verifyNoInteractions; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.annotations.Subscriber; import io.scalecube.services.discovery.api.ServiceDiscoveryEvent; import java.util.concurrent.atomic.AtomicReference; @@ -18,7 +19,7 @@ void testRegisterNonDiscoveryCoreSubscriber() { final NonDiscoverySubscriber1 discoverySubscriber1 = spy(new NonDiscoverySubscriber1()); final NonDiscoverySubscriber2 discoverySubscriber2 = spy(new NonDiscoverySubscriber2()); - Microservices.builder().services(discoverySubscriber1, discoverySubscriber2).startAwait(); + Microservices.start(new Context().services(discoverySubscriber1, discoverySubscriber2)); verifyNoInteractions(discoverySubscriber1, discoverySubscriber2); } @@ -28,7 +29,7 @@ void testRegisterNotMatchingTypeDiscoveryCoreSubscriber() { final NotMatchingTypeDiscoverySubscriber discoverySubscriber = spy(new NotMatchingTypeDiscoverySubscriber()); - Microservices.builder().services(discoverySubscriber).startAwait(); + Microservices.start(new Context().services(discoverySubscriber)); verifyNoInteractions(discoverySubscriber); } @@ -39,7 +40,7 @@ void testRegisterDiscoveryCoreSubscriber() { final NormalDiscoverySubscriber normalDiscoverySubscriber = new NormalDiscoverySubscriber(subscriptionReference); - Microservices.builder().services(normalDiscoverySubscriber).startAwait(); + Microservices.start(new Context().services(normalDiscoverySubscriber)); assertNotNull(subscriptionReference.get(), "subscription"); } diff --git a/services/src/test/java/io/scalecube/services/ServiceLifecycleAnnotationsTest.java b/services/src/test/java/io/scalecube/services/ServiceLifecycleAnnotationsTest.java index 37fbf875f..bd4aaa67a 100644 --- a/services/src/test/java/io/scalecube/services/ServiceLifecycleAnnotationsTest.java +++ b/services/src/test/java/io/scalecube/services/ServiceLifecycleAnnotationsTest.java @@ -5,6 +5,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.annotations.AfterConstruct; import io.scalecube.services.annotations.BeforeDestroy; import io.scalecube.services.annotations.Service; @@ -21,25 +22,25 @@ public class ServiceLifecycleAnnotationsTest extends BaseTest { void testAfterConstructThenBeforeDestroy() { //noinspection EmptyTryBlock,unused try (Microservices microservices = - Microservices.builder() - .services( - ServiceInfo.fromServiceInstance( - new TestService() { - @AfterConstruct - void init() { - afterConstruct.invoke(); - } - }) - .build(), - ServiceInfo.fromServiceInstance( - new TestService() { - @BeforeDestroy - void cleanup() { - beforeDestroy.invoke(); - } - }) - .build()) - .startAwait()) {} + Microservices.start( + new Context() + .services( + ServiceInfo.fromServiceInstance( + new TestService() { + @AfterConstruct + void init() { + afterConstruct.invoke(); + } + }) + .build(), + ServiceInfo.fromServiceInstance( + new TestService() { + @BeforeDestroy + void cleanup() { + beforeDestroy.invoke(); + } + }) + .build()))) {} verify(afterConstruct, times(1)).invoke(); verify(beforeDestroy, times(1)).invoke(); @@ -52,25 +53,25 @@ void testAfterConstructFailsThenBeforeDestroy() { //noinspection EmptyTryBlock,unused try (Microservices microservices = - Microservices.builder() - .services( - ServiceInfo.fromServiceInstance( - new TestService() { - @AfterConstruct - void init() { - afterConstruct.invoke(); - } - }) - .build(), - ServiceInfo.fromServiceInstance( - new TestService() { - @BeforeDestroy - void cleanup() { - beforeDestroy.invoke(); - } - }) - .build()) - .startAwait()) { + Microservices.start( + new Context() + .services( + ServiceInfo.fromServiceInstance( + new TestService() { + @AfterConstruct + void init() { + afterConstruct.invoke(); + } + }) + .build(), + ServiceInfo.fromServiceInstance( + new TestService() { + @BeforeDestroy + void cleanup() { + beforeDestroy.invoke(); + } + }) + .build()))) { } catch (Exception ex) { assertSame(exception, Throwables.getRootCause(ex)); } diff --git a/services/src/test/java/io/scalecube/services/ServiceLocalTest.java b/services/src/test/java/io/scalecube/services/ServiceLocalTest.java index f44a61d79..d20ccf96a 100644 --- a/services/src/test/java/io/scalecube/services/ServiceLocalTest.java +++ b/services/src/test/java/io/scalecube/services/ServiceLocalTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static reactor.core.publisher.Sinks.EmitFailureHandler.FAIL_FAST; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.sut.GreetingRequest; import io.scalecube.services.sut.GreetingResponse; @@ -28,13 +29,13 @@ public class ServiceLocalTest extends BaseTest { @BeforeEach public void setUp() { - microservices = Microservices.builder().services(new GreetingServiceImpl()).startAwait(); + microservices = Microservices.start(new Context().services(new GreetingServiceImpl())); } @AfterEach public void cleanUp() { if (microservices != null) { - microservices.shutdown().block(timeout); + microservices.close(); } } @@ -45,8 +46,8 @@ public void test_local_greeting_request_completes_before_timeout() { // call the service. GreetingResponse result = service - .greetingRequestTimeout(new GreetingRequest("joe", timeout)) - .block(timeout.plusSeconds(1)); + .greetingRequestTimeout(new GreetingRequest("joe", Duration.ofMillis(500))) + .block(timeout.plusMillis(500)); // print the greeting. System.out.println("2. greeting_request_completes_before_timeout : " + result.getResult()); @@ -155,7 +156,7 @@ public void test_local_greeting_request_timeout_expires() { RuntimeException.class, () -> Mono.from(service.greetingRequestTimeout(new GreetingRequest("joe", timeout))) - .timeout(Duration.ofSeconds(1)) + .timeout(Duration.ofMillis(500)) .block()); assertTrue( exception.getCause().getMessage().contains("Did not observe any item or terminal signal")); diff --git a/services/src/test/java/io/scalecube/services/ServiceRegistryTest.java b/services/src/test/java/io/scalecube/services/ServiceRegistryTest.java index d4da76f70..923cc72b1 100644 --- a/services/src/test/java/io/scalecube/services/ServiceRegistryTest.java +++ b/services/src/test/java/io/scalecube/services/ServiceRegistryTest.java @@ -8,6 +8,7 @@ import io.scalecube.cluster.codec.jackson.JacksonMetadataCodec; import io.scalecube.cluster.metadata.JdkMetadataCodec; import io.scalecube.cluster.metadata.MetadataCodec; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.discovery.api.ServiceDiscoveryEvent; import io.scalecube.services.discovery.api.ServiceDiscoveryFactory; @@ -23,7 +24,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; import reactor.test.StepVerifier; @@ -42,10 +42,10 @@ public void test_added_removed_registration_events(MetadataCodec metadataCodec) Sinks.Many events = Sinks.many().replay().all(); Microservices seed = - Microservices.builder() - .discovery(defServiceDiscovery(metadataCodec)) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(metadataCodec)) + .transport(RSocketServiceTransport::new)); seed.listenDiscovery() .subscribe(events::tryEmitNext, events::tryEmitError, events::tryEmitComplete); @@ -53,28 +53,32 @@ public void test_added_removed_registration_events(MetadataCodec metadataCodec) Address seedAddress = seed.discoveryAddress(); Microservices ms1 = - Microservices.builder() - .discovery(defServiceDiscovery(seedAddress, metadataCodec)) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(seedAddress, metadataCodec)) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); Microservices ms2 = - Microservices.builder() - .discovery(defServiceDiscovery(seedAddress, metadataCodec)) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(seedAddress, metadataCodec)) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); StepVerifier.create(events.asFlux().onBackpressureBuffer()) .assertNext(event -> assertEquals(ENDPOINT_ADDED, event.type())) .assertNext(event -> assertEquals(ENDPOINT_ADDED, event.type())) - .then(() -> Mono.whenDelayError(ms1.shutdown(), ms2.shutdown()).block(TIMEOUT)) + .then( + () -> { + ms1.close(); + ms2.close(); + }) .assertNext(event -> assertEquals(ENDPOINT_LEAVING, event.type())) .assertNext(event -> assertEquals(ENDPOINT_LEAVING, event.type())) .assertNext(event -> assertEquals(ENDPOINT_REMOVED, event.type())) .assertNext(event -> assertEquals(ENDPOINT_REMOVED, event.type())) - .then(() -> seed.shutdown().block(TIMEOUT)) + .then(seed::close) .thenCancel() .verify(TIMEOUT); } @@ -87,11 +91,12 @@ public void test_listen_to_discovery_events(MetadataCodec metadataCodec) { List cluster = new CopyOnWriteArrayList<>(); Microservices seed = - Microservices.builder() - .discovery(defServiceDiscovery(metadataCodec)) - .transport(RSocketServiceTransport::new) - .services(new AnnotationServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(metadataCodec)) + .transport(RSocketServiceTransport::new) + .services(new AnnotationServiceImpl())); + cluster.add(seed); seed.listenDiscovery() @@ -103,29 +108,31 @@ public void test_listen_to_discovery_events(MetadataCodec metadataCodec) { .then( () -> { Microservices ms1 = - Microservices.builder() - .discovery(defServiceDiscovery(seedAddress, metadataCodec)) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(seedAddress, metadataCodec)) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); + cluster.add(ms1); }) .assertNext(event -> assertEquals(ENDPOINT_ADDED, event.type())) .then( () -> { Microservices ms2 = - Microservices.builder() - .discovery(defServiceDiscovery(seedAddress, metadataCodec)) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(seedAddress, metadataCodec)) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); + cluster.add(ms2); }) .assertNext(event -> assertEquals(ENDPOINT_ADDED, event.type())) - .then(() -> cluster.remove(2).shutdown().block(TIMEOUT)) + .then(() -> cluster.remove(2).close()) .assertNext(event -> assertEquals(ENDPOINT_LEAVING, event.type())) .assertNext(event -> assertEquals(ENDPOINT_REMOVED, event.type())) - .then(() -> cluster.remove(1).shutdown().block(TIMEOUT)) + .then(() -> cluster.remove(1).close()) .assertNext(event -> assertEquals(ENDPOINT_LEAVING, event.type())) .assertNext(event -> assertEquals(ENDPOINT_REMOVED, event.type())) .thenCancel() @@ -141,8 +148,7 @@ public void test_listen_to_discovery_events(MetadataCodec metadataCodec) { .thenCancel() .verify(TIMEOUT); - Mono.whenDelayError(cluster.stream().map(Microservices::shutdown).toArray(Mono[]::new)) - .block(TIMEOUT); + cluster.forEach(Microservices::close); } @ParameterizedTest @@ -153,11 +159,11 @@ public void test_delayed_listen_to_discovery_events(MetadataCodec metadataCodec) List cluster = new CopyOnWriteArrayList<>(); Microservices seed = - Microservices.builder() - .discovery(defServiceDiscovery(metadataCodec)) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(metadataCodec)) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); cluster.add(seed); seed.listenDiscovery() @@ -169,22 +175,23 @@ public void test_delayed_listen_to_discovery_events(MetadataCodec metadataCodec) .then( () -> { Microservices ms1 = - Microservices.builder() - .discovery(defServiceDiscovery(seedAddress, metadataCodec)) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl(), new AnnotationServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(seedAddress, metadataCodec)) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl(), new AnnotationServiceImpl())); cluster.add(ms1); }) .assertNext(event -> assertEquals(ENDPOINT_ADDED, event.type())) .then( () -> { Microservices ms2 = - Microservices.builder() - .discovery(defServiceDiscovery(seedAddress, metadataCodec)) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery(defServiceDiscovery(seedAddress, metadataCodec)) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); + cluster.add(ms2); }) .assertNext(event -> assertEquals(ENDPOINT_ADDED, event.type())) @@ -197,8 +204,7 @@ public void test_delayed_listen_to_discovery_events(MetadataCodec metadataCodec) .thenCancel() .verify(TIMEOUT); - Mono.whenDelayError(cluster.stream().map(Microservices::shutdown).toArray(Mono[]::new)) - .block(TIMEOUT); + cluster.forEach(Microservices::close); } private ServiceDiscoveryFactory defServiceDiscovery(MetadataCodec metadataCodec) { diff --git a/services/src/test/java/io/scalecube/services/ServiceRemoteTest.java b/services/src/test/java/io/scalecube/services/ServiceRemoteTest.java index 630ac3b52..ca2433924 100644 --- a/services/src/test/java/io/scalecube/services/ServiceRemoteTest.java +++ b/services/src/test/java/io/scalecube/services/ServiceRemoteTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static reactor.core.publisher.Sinks.EmitFailureHandler.FAIL_FAST; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.discovery.api.ServiceDiscovery; @@ -54,40 +55,40 @@ public static void setup() { @AfterAll public static void tearDown() { try { - gateway.shutdown().block(); + gateway.close(); } catch (Exception ignore) { // no-op } try { - provider.shutdown().block(); + provider.close(); } catch (Exception ignore) { // no-op } } private static Microservices gateway() { - return Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + return Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); } private static Microservices serviceProvider() { - return Microservices.builder() - .discovery(ServiceRemoteTest::serviceDiscovery) - .transport(RSocketServiceTransport::new) - .services(new GreetingServiceImpl()) - .startAwait(); + return Microservices.start( + new Context() + .discovery(ServiceRemoteTest::serviceDiscovery) + .transport(RSocketServiceTransport::new) + .services(new GreetingServiceImpl())); } @Test public void test_remote_greeting_request_completes_before_timeout() { - Duration duration = Duration.ofSeconds(1); + Duration duration = Duration.ofMillis(500); GreetingService service = gateway.call().api(GreetingService.class); @@ -106,8 +107,6 @@ public void test_remote_void_greeting() throws Exception { service.greetingVoid(new GreetingRequest("joe")).block(Duration.ofSeconds(3)); System.out.println("test_remote_void_greeting done."); - - Thread.sleep(1000); } @Test @@ -274,11 +273,12 @@ public void test_remote_serviceA_calls_serviceB_using_setter() { // Create microservices instance cluster. // noinspection unused Microservices provider = - Microservices.builder() - .discovery(ServiceRemoteTest::serviceDiscovery) - .transport(RSocketServiceTransport::new) - .services(new CoarseGrainedServiceImpl()) // add service a and b - .startAwait(); + Microservices.start( + new Context() + .discovery(ServiceRemoteTest::serviceDiscovery) + .transport(RSocketServiceTransport::new) + .services(new CoarseGrainedServiceImpl()) // add service a and b + ); // Get a proxy to the service api. CoarseGrainedService service = gateway.call().api(CoarseGrainedService.class); @@ -286,7 +286,7 @@ public void test_remote_serviceA_calls_serviceB_using_setter() { Publisher future = service.callGreeting("joe"); assertEquals(" hello to: joe", Mono.from(future).block(Duration.ofSeconds(1))); - provider.shutdown().then(Mono.delay(TIMEOUT2)).block(); + provider.close(); } @Test @@ -297,17 +297,17 @@ public void test_remote_serviceA_calls_serviceB() { // Create microservices instance cluster. // noinspection unused Microservices provider = - Microservices.builder() - .discovery(ServiceRemoteTest::serviceDiscovery) - .transport(RSocketServiceTransport::new) - .services(another) - .startAwait(); + Microservices.start( + new Context() + .discovery(ServiceRemoteTest::serviceDiscovery) + .transport(RSocketServiceTransport::new) + .services(another)); // Get a proxy to the service api. CoarseGrainedService service = gateway.call().api(CoarseGrainedService.class); Publisher future = service.callGreeting("joe"); assertEquals(" hello to: joe", Mono.from(future).block(Duration.ofSeconds(1))); - provider.shutdown().then(Mono.delay(TIMEOUT2)).block(); + provider.close(); } @Test @@ -317,11 +317,12 @@ public void test_remote_serviceA_calls_serviceB_with_timeout() { // Create microservices instance cluster. Microservices ms = - Microservices.builder() - .discovery(ServiceRemoteTest::serviceDiscovery) - .transport(RSocketServiceTransport::new) - .services(another) // add service a and b - .startAwait(); + Microservices.start( + new Context() + .discovery(ServiceRemoteTest::serviceDiscovery) + .transport(RSocketServiceTransport::new) + .services(another) // add service a and b + ); // Get a proxy to the service api. CoarseGrainedService service = gateway.call().api(CoarseGrainedService.class); @@ -330,8 +331,7 @@ public void test_remote_serviceA_calls_serviceB_with_timeout() { InternalServiceException.class, () -> Mono.from(service.callGreetingTimeout("joe")).block()); assertTrue(exception.getMessage().contains("Did not observe any item or terminal signal")); - System.out.println("done"); - ms.shutdown().then(Mono.delay(TIMEOUT2)).block(); + ms.close(); } @Test @@ -342,11 +342,12 @@ public void test_remote_serviceA_calls_serviceB_with_dispatcher() { // Create microservices instance cluster. Microservices provider = - Microservices.builder() - .discovery(ServiceRemoteTest::serviceDiscovery) - .transport(RSocketServiceTransport::new) - .services(another) // add service a and b - .startAwait(); + Microservices.start( + new Context() + .discovery(ServiceRemoteTest::serviceDiscovery) + .transport(RSocketServiceTransport::new) + .services(another) // add service a and b + ); // Get a proxy to the service api. CoarseGrainedService service = gateway.call().api(CoarseGrainedService.class); @@ -354,7 +355,7 @@ public void test_remote_serviceA_calls_serviceB_with_dispatcher() { String response = service.callGreetingWithDispatcher("joe").block(Duration.ofSeconds(5)); assertEquals(response, " hello to: joe"); - provider.shutdown().then(Mono.delay(TIMEOUT2)).block(); + provider.close(); } @Test @@ -504,16 +505,16 @@ public void test_services_contribute_to_cluster_metadata() { tags.put("HOSTNAME", "host1"); Microservices ms = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .tags(tags) - .services(new GreetingServiceImpl()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .tags(tags) + .services(new GreetingServiceImpl())); assertTrue(ms.serviceEndpoint().tags().containsKey("HOSTNAME")); } diff --git a/services/src/test/java/io/scalecube/services/StreamingServiceTest.java b/services/src/test/java/io/scalecube/services/StreamingServiceTest.java index 025053d1a..d6e7774eb 100644 --- a/services/src/test/java/io/scalecube/services/StreamingServiceTest.java +++ b/services/src/test/java/io/scalecube/services/StreamingServiceTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.sut.QuoteService; @@ -28,30 +29,30 @@ public class StreamingServiceTest extends BaseTest { @BeforeAll public static void setup() { gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .defaultDataDecoder(ServiceMessageCodec::decodeData) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new) + .defaultDataDecoder(ServiceMessageCodec::decodeData)); final Address gatewayAddress = gateway.discoveryAddress(); node = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .defaultDataDecoder(ServiceMessageCodec::decodeData) - .services(new SimpleQuoteService()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .defaultDataDecoder(ServiceMessageCodec::decodeData) + .services(new SimpleQuoteService())); } @Test @@ -77,10 +78,9 @@ public void test_local_quotes_service() { QuoteService service = node.call().api(QuoteService.class); - int expected = 3; - List list = service.quotes().take(Duration.ofMillis(3500)).collectList().block(); + List list = service.quotes().take(Duration.ofMillis(500)).collectList().block(); - assertEquals(expected, list.size()); + assertTrue(list.size() > 1, "list.size"); } @Test @@ -159,11 +159,10 @@ public void test_scheduled_messages() { ServiceMessage scheduled = ServiceMessage.builder().qualifier(QuoteService.NAME, "scheduled").data(1000).build(); - int expected = 3; List list = - serviceCall.requestMany(scheduled).take(Duration.ofSeconds(4)).collectList().block(); + serviceCall.requestMany(scheduled).take(Duration.ofMillis(500)).collectList().block(); - assertEquals(expected, list.size()); + assertTrue(list.size() > 1, "list.size"); } @Test diff --git a/services/src/test/java/io/scalecube/services/routings/RoutersTest.java b/services/src/test/java/io/scalecube/services/routings/RoutersTest.java index 05ed4d079..17591573f 100644 --- a/services/src/test/java/io/scalecube/services/routings/RoutersTest.java +++ b/services/src/test/java/io/scalecube/services/routings/RoutersTest.java @@ -12,6 +12,7 @@ import io.scalecube.services.Address; import io.scalecube.services.BaseTest; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.Reflect; import io.scalecube.services.ServiceCall; import io.scalecube.services.ServiceInfo; @@ -35,7 +36,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Optional; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -56,81 +56,81 @@ public class RoutersTest extends BaseTest { @BeforeAll public static void setup() { gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); gatewayAddress = gateway.discoveryAddress(); // Create microservices instance cluster. provider1 = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services( - ServiceInfo.fromServiceInstance(new GreetingServiceImpl(1)) - .tag("ONLYFOR", "joe") - .tag("SENDER", "1") - .build(), - ServiceInfo.fromServiceInstance(new GreetingServiceImplA()) - .tag("Weight", "0.1") - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services( + ServiceInfo.fromServiceInstance(new GreetingServiceImpl(1)) + .tag("ONLYFOR", "joe") + .tag("SENDER", "1") + .build(), + ServiceInfo.fromServiceInstance(new GreetingServiceImplA()) + .tag("Weight", "0.1") + .build())); // Create microservices instance cluster. provider2 = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services( - ServiceInfo.fromServiceInstance(new GreetingServiceImpl(2)) - .tag("ONLYFOR", "fransin") - .tag("SENDER", "2") - .build(), - ServiceInfo.fromServiceInstance(new GreetingServiceImplB()) - .tag("Weight", "0.9") - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services( + ServiceInfo.fromServiceInstance(new GreetingServiceImpl(2)) + .tag("ONLYFOR", "fransin") + .tag("SENDER", "2") + .build(), + ServiceInfo.fromServiceInstance(new GreetingServiceImplB()) + .tag("Weight", "0.9") + .build())); TagService tagService = input -> input.map(String::toUpperCase); provider3 = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services( - ServiceInfo.fromServiceInstance(tagService) - .tag("tagB", "bb") - .tag("tagC", "c") - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services( + ServiceInfo.fromServiceInstance(tagService) + .tag("tagB", "bb") + .tag("tagC", "c") + .build())); } @AfterAll public static void tearDown() { - gateway.shutdown().block(); - provider1.shutdown().block(); - provider2.shutdown().block(); - provider3.shutdown().block(); + gateway.close(); + provider1.close(); + provider2.close(); + provider3.close(); } @Test @@ -162,7 +162,7 @@ public void test_round_robin() { } @Test - public void test_remote_service_tags() throws Exception { + public void test_remote_service_tags() { CanaryService service = gateway @@ -170,8 +170,6 @@ public void test_remote_service_tags() throws Exception { .router(Routers.getRouter(WeightedRandomRouter.class)) .api(CanaryService.class); - Thread.sleep(1000); - AtomicInteger serviceBCount = new AtomicInteger(0); int n = (int) 1e3; @@ -261,9 +259,7 @@ public void test_tag_request_selection_logic() { } @Test - public void test_service_tags() throws Exception { - - TimeUnit.SECONDS.sleep(3); + public void test_service_tags() { ServiceCall service = gateway.call().router(WeightedRandomRouter.class); ServiceMessage req = diff --git a/services/src/test/java/io/scalecube/services/routings/ServiceTagsExample.java b/services/src/test/java/io/scalecube/services/routings/ServiceTagsExample.java index d11f07e7a..d99386c84 100644 --- a/services/src/test/java/io/scalecube/services/routings/ServiceTagsExample.java +++ b/services/src/test/java/io/scalecube/services/routings/ServiceTagsExample.java @@ -2,6 +2,7 @@ import io.scalecube.services.Address; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceInfo; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; import io.scalecube.services.routings.sut.CanaryService; @@ -22,46 +23,46 @@ public class ServiceTagsExample { */ public static void main(String[] args) { Microservices gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); Address seedAddress = gateway.discoveryAddress(); Microservices services1 = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services( - ServiceInfo.fromServiceInstance(new GreetingServiceImplA()) - .tag("Weight", "0.3") - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services( + ServiceInfo.fromServiceInstance(new GreetingServiceImplA()) + .tag("Weight", "0.3") + .build())); Microservices services2 = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services( - ServiceInfo.fromServiceInstance(new GreetingServiceImplB()) - .tag("Weight", "0.7") - .build()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(seedAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services( + ServiceInfo.fromServiceInstance(new GreetingServiceImplB()) + .tag("Weight", "0.7") + .build())); CanaryService service = gateway.call().router(WeightedRandomRouter.class).api(CanaryService.class); diff --git a/services/src/test/java/io/scalecube/services/sut/SimpleQuoteService.java b/services/src/test/java/io/scalecube/services/sut/SimpleQuoteService.java index 7c418f801..ed4fa33b9 100644 --- a/services/src/test/java/io/scalecube/services/sut/SimpleQuoteService.java +++ b/services/src/test/java/io/scalecube/services/sut/SimpleQuoteService.java @@ -19,12 +19,12 @@ public Mono justOne() { @Override public Flux scheduled(int interval) { - return Flux.interval(Duration.ofSeconds(1)).map(s -> "quote : " + counter.incrementAndGet()); + return Flux.interval(Duration.ofMillis(100)).map(s -> "quote : " + counter.incrementAndGet()); } @Override public Flux quotes() { - return Flux.interval(Duration.ofSeconds(1)).map(s -> "quote : " + counter.incrementAndGet()); + return Flux.interval(Duration.ofMillis(100)).map(s -> "quote : " + counter.incrementAndGet()); } @Override diff --git a/services/src/test/java/io/scalecube/services/transport/rsocket/RSocketNettyColocatedEventLoopGroupTest.java b/services/src/test/java/io/scalecube/services/transport/rsocket/RSocketNettyColocatedEventLoopGroupTest.java index 71aee1a36..175bef1b7 100644 --- a/services/src/test/java/io/scalecube/services/transport/rsocket/RSocketNettyColocatedEventLoopGroupTest.java +++ b/services/src/test/java/io/scalecube/services/transport/rsocket/RSocketNettyColocatedEventLoopGroupTest.java @@ -5,6 +5,7 @@ import io.scalecube.services.Address; import io.scalecube.services.BaseTest; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.annotations.Inject; import io.scalecube.services.annotations.Service; @@ -28,54 +29,54 @@ public class RSocketNettyColocatedEventLoopGroupTest extends BaseTest { @BeforeEach public void setUp() { this.gateway = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint))) + .transport(RSocketServiceTransport::new)); final Address gatewayAddress = this.gateway.discoveryAddress(); Microservices facade = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new Facade()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new Facade())); final Address facadeAddress = facade.discoveryAddress(); this.ping = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(facadeAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services((PingService) () -> Mono.just(Thread.currentThread().getName())) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(facadeAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services((PingService) () -> Mono.just(Thread.currentThread().getName()))); this.pong = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint)) - .membership(cfg -> cfg.seedMembers(facadeAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services((PongService) () -> Mono.just(Thread.currentThread().getName())) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint)) + .membership(cfg -> cfg.seedMembers(facadeAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services((PongService) () -> Mono.just(Thread.currentThread().getName()))); } @Test @@ -94,15 +95,9 @@ public void testColocatedEventLoopGroup() { @AfterEach public void tearDown() { - try { - Mono.whenDelayError( - Optional.ofNullable(gateway).map(Microservices::shutdown).orElse(Mono.empty()), - Optional.ofNullable(ping).map(Microservices::shutdown).orElse(Mono.empty()), - Optional.ofNullable(pong).map(Microservices::shutdown).orElse(Mono.empty())) - .block(); - } catch (Throwable ignore) { - // no-op - } + Optional.ofNullable(gateway).ifPresent(Microservices::close); + Optional.ofNullable(ping).ifPresent(Microservices::close); + Optional.ofNullable(pong).ifPresent(Microservices::close); } @Service("facade") diff --git a/services/src/test/java/io/scalecube/services/transport/rsocket/RSocketServiceTransportTest.java b/services/src/test/java/io/scalecube/services/transport/rsocket/RSocketServiceTransportTest.java index 0c41f4ab6..a80249361 100644 --- a/services/src/test/java/io/scalecube/services/transport/rsocket/RSocketServiceTransportTest.java +++ b/services/src/test/java/io/scalecube/services/transport/rsocket/RSocketServiceTransportTest.java @@ -7,6 +7,7 @@ import io.scalecube.services.Address; import io.scalecube.services.BaseTest; import io.scalecube.services.Microservices; +import io.scalecube.services.Microservices.Context; import io.scalecube.services.ServiceCall; import io.scalecube.services.api.ServiceMessage; import io.scalecube.services.discovery.ScalecubeServiceDiscovery; @@ -25,7 +26,6 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import reactor.core.Disposable; -import reactor.core.publisher.Mono; public class RSocketServiceTransportTest extends BaseTest { @@ -43,40 +43,34 @@ public class RSocketServiceTransportTest extends BaseTest { @BeforeEach public void setUp() { gateway = - Microservices.builder() - .discovery( - endpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(endpoint))) - .transport(RSocketServiceTransport::new) - .startAwait(); + Microservices.start( + new Context() + .discovery( + endpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(endpoint))) + .transport(RSocketServiceTransport::new)); final Address gatewayAddress = this.gateway.discoveryAddress(); serviceNode = - Microservices.builder() - .discovery( - serviceEndpoint -> - new ScalecubeServiceDiscovery() - .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) - .options(opts -> opts.metadata(serviceEndpoint)) - .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) - .transport(RSocketServiceTransport::new) - .services(new SimpleQuoteService()) - .startAwait(); + Microservices.start( + new Context() + .discovery( + serviceEndpoint -> + new ScalecubeServiceDiscovery() + .transport(cfg -> cfg.transportFactory(new WebsocketTransportFactory())) + .options(opts -> opts.metadata(serviceEndpoint)) + .membership(cfg -> cfg.seedMembers(gatewayAddress.toString()))) + .transport(RSocketServiceTransport::new) + .services(new SimpleQuoteService())); } @AfterEach public void cleanUp() { - try { - Mono.whenDelayError( - Optional.ofNullable(gateway).map(Microservices::shutdown).orElse(Mono.empty()), - Optional.ofNullable(serviceNode).map(Microservices::shutdown).orElse(Mono.empty())) - .block(); - } catch (Throwable ignore) { - // no-op - } + Optional.ofNullable(gateway).ifPresent(Microservices::close); + Optional.ofNullable(serviceNode).ifPresent(Microservices::close); } @Disabled @@ -98,7 +92,7 @@ public void test_remote_node_died_mono_never() throws Exception { // service node goes down TimeUnit.SECONDS.sleep(3); - serviceNode.shutdown().block(TIMEOUT); + serviceNode.close(); if (!latch.await(20, TimeUnit.SECONDS)) { fail("latch.await"); @@ -128,15 +122,12 @@ public void test_remote_node_died_many_never() throws Exception { .subscribe(onNext -> latch.countDown(), System.err::println); // service node goes down - TimeUnit.SECONDS.sleep(3); - serviceNode.shutdown().block(TIMEOUT); + serviceNode.close(); if (!latch.await(20, TimeUnit.SECONDS)) { fail("latch.await"); } - TimeUnit.MILLISECONDS.sleep(1000); - assertEquals(0, latch.getCount()); assertEquals(ConnectionClosedException.class, exceptionHolder.get().getClass()); assertTrue(sub1.get().isDisposed()); @@ -163,15 +154,12 @@ public void test_remote_node_died_many_then_never() throws Exception { .subscribe(onNext -> latch.countDown(), System.err::println); // service node goes down - TimeUnit.SECONDS.sleep(3); - serviceNode.shutdown().block(TIMEOUT); + serviceNode.close(); if (!latch.await(20, TimeUnit.SECONDS)) { fail("latch.await"); } - TimeUnit.MILLISECONDS.sleep(1000); - assertEquals(0, latch.getCount()); assertEquals(ConnectionClosedException.class, exceptionHolder.get().getClass()); assertTrue(sub1.get().isDisposed());