Skip to content

Commit

Permalink
Merge pull request #523 from cescoffier/add-path-to-service-instance
Browse files Browse the repository at this point in the history
  • Loading branch information
cescoffier authored Mar 27, 2023
2 parents b556477 + e1aff8f commit 47a1285
Show file tree
Hide file tree
Showing 29 changed files with 182 additions and 371 deletions.
127 changes: 4 additions & 123 deletions api/revapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,131 +27,12 @@
"criticality" : "highlight",
"minSeverity" : "POTENTIALLY_BREAKING",
"minCriticality" : "documented",
"differences" : [{
"ignore": true,
"code": "java.method.returnTypeTypeParametersChanged",
"old": "method io.smallrye.stork.api.Metadata<? extends io.smallrye.stork.api.MetadataKey> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T>>::empty()",
"new": "method <T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey> io.smallrye.stork.api.Metadata<T> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey>::empty()",
"justification": "Refactored according with the actual type parameter change."

},
"differences" : [
{
"ignore": true,
"code": "java.generics.elementNowParameterized",
"old": "method io.smallrye.stork.api.Metadata<? extends io.smallrye.stork.api.MetadataKey> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T>>::empty()",
"new": "method <T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey> io.smallrye.stork.api.Metadata<T> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey>::empty()",
"justification": "Using a generic method that operates in a parametrized type."

},
{
"ignore": true,
"code": "java.generics.formalTypeParameterAdded",
"old": "method io.smallrye.stork.api.Metadata<? extends io.smallrye.stork.api.MetadataKey> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T>>::empty()",
"new": "method <T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey> io.smallrye.stork.api.Metadata<T> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey>::empty()",
"typeParameter": "T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey",
"justification": "Add a type parameter representing the element type according with the actual type parameter of the class."

},
{
"ignore": true,
"code": "java.method.returnTypeTypeParametersChanged",
"old": "method java.util.EnumMap<T, java.lang.Object> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T>>::getMetadata()",
"new": "method java.util.EnumMap<T, java.lang.Object> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey>::getMetadata()",
"justification": "Refactored according with the actual type parameter change."

},
{
"ignore": true,
"code": "java.method.parameterTypeParameterChanged",
"old": "parameter io.smallrye.stork.api.Metadata<T> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T>>::with(===T===, java.lang.Object)",
"new": "parameter io.smallrye.stork.api.Metadata<T> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey>::with(===T===, java.lang.Object)",
"parameterIndex": "0",
"justification": "Refactored according with the actual type parameter change."

},
{
"ignore": true,
"code": "java.method.returnTypeTypeParametersChanged",
"old": "method io.smallrye.stork.api.Metadata<T> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T>>::with(T, java.lang.Object)",
"new": "method io.smallrye.stork.api.Metadata<T> io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey>::with(T, java.lang.Object)",
"justification": "Refactored according with the actual type parameter change."

},
{
"ignore": true,
"code": "java.generics.formalTypeParameterChanged",
"old": "class io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T>>",
"new": "class io.smallrye.stork.api.Metadata<T extends java.lang.Enum<T> & io.smallrye.stork.api.MetadataKey>",
"justification": "Adjust the formal type parameter and remove bounded wildcard types used."

},
{
"ignore": true,
"code": "java.method.returnTypeChanged",
"old": "method io.smallrye.stork.api.config.LoadBalancerConfig io.smallrye.stork.api.ServiceDefinition::getLoadBalancer()",
"new": "method io.smallrye.stork.api.config.ConfigWithType io.smallrye.stork.api.ServiceDefinition::getLoadBalancer()",
"justification": "Refactored according with the renaming of the returned type."
},
{
"ignore": true,
"code": "java.method.returnTypeChanged",
"old": "method io.smallrye.stork.api.config.ServiceDiscoveryConfig io.smallrye.stork.api.ServiceDefinition::getServiceDiscovery()",
"new": "method io.smallrye.stork.api.config.ConfigWithType io.smallrye.stork.api.ServiceDefinition::getServiceDiscovery()",
"justification": "Refactored according with the renaming of the returned type."
},
{
"ignore": true,
"code": "java.method.parameterTypeChanged",
"old": "parameter io.smallrye.stork.api.ServiceDefinition io.smallrye.stork.api.ServiceDefinition::of(===io.smallrye.stork.api.config.ServiceDiscoveryConfig===)",
"new": "parameter io.smallrye.stork.api.ServiceDefinition io.smallrye.stork.api.ServiceDefinition::of(===io.smallrye.stork.api.config.ConfigWithType===)",
"parameterIndex": "0",
"justification": "Refactored according with the renaming of the parameter type."

},
{
"ignore": true,
"code": "java.method.parameterTypeChanged",
"old": "parameter io.smallrye.stork.api.ServiceDefinition io.smallrye.stork.api.ServiceDefinition::of(===io.smallrye.stork.api.config.ServiceDiscoveryConfig===, io.smallrye.stork.api.config.LoadBalancerConfig)",
"new": "parameter io.smallrye.stork.api.ServiceDefinition io.smallrye.stork.api.ServiceDefinition::of(===io.smallrye.stork.api.config.ConfigWithType===, io.smallrye.stork.api.config.ConfigWithType)",
"parameterIndex": "0",
"justification": "Refactored according with the renaming of the parameter type."

},
{
"ignore": true,
"code": "java.method.parameterTypeChanged",
"old": "parameter io.smallrye.stork.api.ServiceDefinition io.smallrye.stork.api.ServiceDefinition::of(io.smallrye.stork.api.config.ServiceDiscoveryConfig, ===io.smallrye.stork.api.config.LoadBalancerConfig===)",
"new": "parameter io.smallrye.stork.api.ServiceDefinition io.smallrye.stork.api.ServiceDefinition::of(io.smallrye.stork.api.config.ConfigWithType, ===io.smallrye.stork.api.config.ConfigWithType===)",
"parameterIndex": "1",
"justification": "Refactored according with the renaming of the returned type."

},
{
"ignore": true,
"code": "java.class.removed",
"old": "interface io.smallrye.stork.api.config.LoadBalancerConfig",
"justification": "Replaced by io.smallrye.stork.api.config.ConfigWithType."

},
{
"ignore": true,
"code": "java.method.returnTypeChanged",
"old": "method io.smallrye.stork.api.config.LoadBalancerConfig io.smallrye.stork.api.config.ServiceConfig::loadBalancer()",
"new": "method io.smallrye.stork.api.config.ConfigWithType io.smallrye.stork.api.config.ServiceConfig::loadBalancer()",
"justification": "Refactored according with the renaming of the returned type."
},
{
"ignore": true,
"code": "java.method.returnTypeChanged",
"old": "method io.smallrye.stork.api.config.ServiceDiscoveryConfig io.smallrye.stork.api.config.ServiceConfig::serviceDiscovery()",
"new": "method io.smallrye.stork.api.config.ConfigWithType io.smallrye.stork.api.config.ServiceConfig::serviceDiscovery()",
"justification": "Refactored according with the renaming of the returned type."
},
{
"ignore": true,
"code": "java.class.removed",
"old": "interface io.smallrye.stork.api.config.ServiceDiscoveryConfig",
"justification": "Replaced by io.smallrye.stork.api.config.ConfigWithType."
"code": "java.method.addedToInterface",
"new": "method java.util.Optional<java.lang.String> io.smallrye.stork.api.ServiceInstance::getPath()",
"justification": "New method to handle API gateways"
}
]
}
Expand Down
13 changes: 11 additions & 2 deletions api/src/main/java/io/smallrye/stork/api/ServiceInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;

/**
* Represents an instance of service.
Expand All @@ -24,6 +25,14 @@ public interface ServiceInstance {
*/
int getPort();

/**
* For service behind an API gateway or a proxy, this method return the path.
* When set, the final location of the service is composed of {@code $host:$port/$path}.
*
* @return the path if any.
*/
Optional<String> getPath();

/**
* @return whether the communication should happen over a secure connection
*/
Expand Down Expand Up @@ -58,7 +67,7 @@ default boolean gatherStatistics() {
*
* <br>
* When {@code gatherStatistics} is enabled, reports the start of an operation using this service instance.
*
* <p>
* The load balancers that keep track of inflight operations should increase the counter on this method.
* The load balancer that collect times of operations should only take into account operations that have
* {@code measureTime} set to {@code true}
Expand All @@ -70,7 +79,7 @@ default void recordStart(boolean measureTime) {

/**
* When {@code gatherStatistics} is enabled, reports a reply for an operation using this service instance.
*
* <p>
* Should be called if and only if {@code recordStart(true)} has been called earlier
*/
default void recordReply() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.smallrye.stork.api;

import java.util.Map;
import java.util.Optional;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
Expand All @@ -26,6 +27,11 @@ public int getPort() {
return 0;
}

@Override
public Optional<String> getPath() {
return Optional.empty();
}

@Override
public boolean isSecure() {
return false;
Expand Down
8 changes: 3 additions & 5 deletions core/revapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@
"differences" : [
{
"ignore": true,
"code": "java.annotation.added",
"old": "class io.smallrye.stork.impl.RoundRobinLoadBalancerProviderLoader",
"new": "class io.smallrye.stork.impl.RoundRobinLoadBalancerProviderLoader",
"annotation": "@jakarta.enterprise.context.ApplicationScoped",
"justification": "Load Balancer can now be CDI beans"
"code": "java.method.addedToInterface",
"new": "method java.util.Optional<java.lang.String> io.smallrye.stork.api.ServiceInstance::getPath()",
"justification": "New method to handle API gateways"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import java.util.Collections;
import java.util.Map;
import java.util.Optional;

import io.smallrye.stork.api.Metadata;
import io.smallrye.stork.api.MetadataKey;
import io.smallrye.stork.api.ServiceInstance;

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class DefaultServiceInstance implements ServiceInstance {

private final long id;
Expand All @@ -17,21 +19,45 @@ public class DefaultServiceInstance implements ServiceInstance {

private final boolean secure;

private final Optional<String> path;

private final Map<String, String> labels;

private Metadata<? extends MetadataKey> metadata;
private final Metadata<? extends MetadataKey> metadata;

public DefaultServiceInstance(long id, String host, int port, String path, boolean secure) {
this(id, host, port, Optional.ofNullable(path), secure, Collections.emptyMap(),
Metadata.empty());
}

public DefaultServiceInstance(long id, String host, int port, Optional<String> path, boolean secure) {
this(id, host, port, path, secure, Collections.emptyMap(),
Metadata.empty());
}

public DefaultServiceInstance(long id, String host, int port, boolean secure) {
this(id, host, port, secure, Collections.emptyMap(),
this(id, host, port, Optional.empty(), secure, Collections.emptyMap(),
Metadata.empty());
}

public DefaultServiceInstance(long id, String host, int port, boolean secure, Metadata<? extends MetadataKey> metadata) {
this(id, host, port, Optional.empty(), secure, Collections.emptyMap(),
metadata);
}

public DefaultServiceInstance(long id, String host, int port, boolean secure, Map<String, String> labels,
Metadata<? extends MetadataKey> metadata) {
this(id, host, port, Optional.empty(), secure, labels, metadata);
}

public DefaultServiceInstance(long id, String host, int port, Optional<String> path, boolean secure,
Map<String, String> labels,
Metadata<? extends MetadataKey> metadata) {
this.id = id;
this.host = host;
this.port = port;
this.secure = secure;
this.path = path;
this.labels = Collections.unmodifiableMap(labels);
this.metadata = metadata;
}
Expand All @@ -51,6 +77,11 @@ public int getPort() {
return port;
}

@Override
public Optional<String> getPath() {
return path;
}

@Override
public boolean isSecure() {
return secure;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.smallrye.stork.impl;

import java.util.Optional;

import io.smallrye.stork.api.ServiceInstance;
import io.smallrye.stork.spi.CallStatisticsCollector;

Expand Down Expand Up @@ -34,6 +36,11 @@ public int getPort() {
return delegate.getPort();
}

@Override
public Optional<String> getPath() {
return delegate.getPath();
}

@Override
public boolean isSecure() {
return delegate.isSecure();
Expand Down
22 changes: 21 additions & 1 deletion core/src/main/java/io/smallrye/stork/utils/HostAndPort.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package io.smallrye.stork.utils;

import java.util.Optional;

/**
* Structure representing a host:port address.
*/
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class HostAndPort {
/**
* The host.
Expand All @@ -13,14 +16,31 @@ public class HostAndPort {
*/
public final int port;

/**
* The path, if any.
*/
public final Optional<String> path;

/**
* Creates a new HostAndPort
*
* @param host the host
* @param port the port
* @param path the path, can be {@code null}
*/
public HostAndPort(String host, int port) {
public HostAndPort(String host, int port, String path) {
this.host = host;
this.port = port;
this.path = Optional.ofNullable(path);
}

/**
* Creates a new HostAndPort
*
* @param host the host
* @param port the port
*/
public HostAndPort(String host, int port) {
this(host, port, null);
}
}
26 changes: 20 additions & 6 deletions core/src/main/java/io/smallrye/stork/utils/StorkAddressUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,36 @@ public static HostAndPort parseToHostAndPort(String address,
if (address.charAt(0) == '[') {
return parseIpV6AddressWithSquareBracket(address, defaultPort, configPlace);
} else if (countColons(address) > 1) {
// IPv6.
return new HostAndPort(address, defaultPort);
} else {
return parseNonIpv6Adress(address, defaultPort, configPlace);
return parseNonIpv6Address(address, defaultPort, configPlace);
}
}

private static HostAndPort parseNonIpv6Adress(String serviceAddress, int defaultPort, String serviceName) {
private static HostAndPort parseNonIpv6Address(String serviceAddress, int defaultPort, String serviceName) {
String[] hostAndMaybePort = serviceAddress.split(":");

switch (hostAndMaybePort.length) {
case 1:
return new HostAndPort(serviceAddress, defaultPort);
case 1: {
int idx = serviceAddress.indexOf("/");
if (idx == -1) {
return new HostAndPort(serviceAddress, defaultPort);
} else {
return new HostAndPort(serviceAddress.substring(0, idx), defaultPort,
serviceAddress.substring(idx));
}
}
case 2:
try {
int port = Integer.parseInt(hostAndMaybePort[1]);
return new HostAndPort(hostAndMaybePort[0], port);
int idx = hostAndMaybePort[1].indexOf("/");
if (idx == -1) {
int port = Integer.parseInt(hostAndMaybePort[1]);
return new HostAndPort(hostAndMaybePort[0], port);
} else {
int port = Integer.parseInt(hostAndMaybePort[1].substring(0, idx));
return new HostAndPort(hostAndMaybePort[0], port, hostAndMaybePort[1].substring(idx));
}
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException(format("Invalid port '%s' in address '%s' for service '%s'",
hostAndMaybePort[1], serviceAddress, serviceName), nfe);
Expand Down
Loading

0 comments on commit 47a1285

Please sign in to comment.