14 | * This retrieval is an asynchronous action, thus, the method returns a {@link Uni}
15 | *
16 | * @return all `ServiceInstance`'s for the service
17 | */
18 | Uni> getServiceInstances();
19 |
20 | /**
21 | * Optional initialization.
22 | * This method will be invoked after all service discoveries and load balancers are registered in Stork
23 | *
24 | * @param stork the stork instance managing the service.
25 | */
26 | default void initialize(StorkServiceRegistry stork) {
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/ServiceRegistrar.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api;
2 |
3 | import io.smallrye.mutiny.Uni;
4 |
5 | public interface ServiceRegistrar & MetadataKey> {
6 |
7 | default Uni registerServiceInstance(String serviceName, String ipAddress, int defaultPort) {
8 | checkAddressNotNull(ipAddress);
9 | return registerServiceInstance(serviceName, Metadata.empty(), ipAddress, defaultPort);
10 | }
11 |
12 | default void checkAddressNotNull(String ipAddress) {
13 | if (ipAddress == null || ipAddress.isEmpty() || ipAddress.isBlank()) {
14 | throw new IllegalArgumentException("Parameter ipAddress should be provided.");
15 | }
16 | }
17 |
18 | Uni registerServiceInstance(String serviceName, Metadata metadata, String ipAddress,
19 | int defaultPort);
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/StorkServiceRegistry.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api;
2 |
3 | import java.util.Map;
4 | import java.util.Optional;
5 |
6 | /**
7 | * The central API of Stork
8 | */
9 | public interface StorkServiceRegistry {
10 |
11 | /**
12 | * Retrieves the {@link Service} associated with the given name.
13 | *
14 | * @param serviceName the service name, must not be {@code null}
15 | * @return the service
16 | * @throws NoSuchServiceDefinitionException if there is no service associated with the given name.
17 | */
18 | Service getService(String serviceName);
19 |
20 | /**
21 | * Retrieves the {@link Service} associated with the given name.
22 | * Unlike {@link #getService(String)} this method returns an {@link Optional} and so does not throw a
23 | * {@link NoSuchServiceDefinitionException} if there is no {@link Service} associated with the given name.
24 | *
25 | * @param serviceName the service name, must not be {@code null}
26 | * @return an {@link Optional} containing the {@link Service} if any, empty otherwise.
27 | */
28 | Optional getServiceOptional(String serviceName);
29 |
30 | /**
31 | * Adds a service to the list of services managed by Stork.
32 | * The service is only added if there is no service with that name already defined.
33 | * Otherwise, the service definition is ignored.
34 | *
35 | * @param name the service name, must not be {@code null} or blank
36 | * @param definition the definition, must not be {@code null}
37 | * @return the Stork instance.
38 | * // TODO Define exception.
39 | */
40 | StorkServiceRegistry defineIfAbsent(String name, ServiceDefinition definition);
41 |
42 | /**
43 | * @return all the services managed by Stork. The returned map is immutable.
44 | */
45 | Map getServices();
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ConfigWithType.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import java.util.Map;
4 |
5 | /**
6 | * Load balancer configuration. Only used internally. The configuration is translated to an object
7 | * that provides parameters through getters
8 | */
9 | public interface ConfigWithType {
10 |
11 | /**
12 | * Load balancer type, e.g. "round-robin".
13 | * A LoadBalancerProvider for the type has to be available
14 | *
15 | * @return load balancer type
16 | */
17 | String type();
18 |
19 | /**
20 | * Load Balancer parameters.
21 | *
22 | * @return map of parameters of the load balancer
23 | */
24 | Map parameters();
25 | }
26 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/Constants.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | /**
4 | * Constants for the main API classes
5 | */
6 | public class Constants {
7 | /**
8 | * Marker value for the default value, used in main API module annotations
9 | */
10 | public static final String DEFAULT_VALUE = "__$$_DEFAULT_VALUE_$$__";
11 | }
12 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/LoadBalancerAttribute.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import static java.lang.annotation.ElementType.TYPE;
4 |
5 | import java.lang.annotation.Repeatable;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | /**
11 | * Defines an attribute for a load balancer.
12 | *
13 | * The name of the attribute corresponds to the value used in the configuration, e.g. for name {@code my-attribute},
14 | * use the following to set the value:
15 | * {@code stork..load-balancer.my-attribute}
16 | *
17 | * In the configuration class generated for the load balancer, this attribute will be exposed through {@code getMyAttribute()}
18 | */
19 | @Retention(RetentionPolicy.RUNTIME)
20 | @Target(TYPE)
21 | @Repeatable(LoadBalancerAttributes.class)
22 | public @interface LoadBalancerAttribute {
23 | /**
24 | * Attribute name as used in the configuration. Exposed through a getter with name converted to camelCase with
25 | * characters that cannot be used in a java identifiers filtered out.
26 | *
27 | * @return the name of the configuration property
28 | */
29 | String name();
30 |
31 | /**
32 | * Default value for the attribute. If not provided and user didn't set the value - null will be passed
33 | *
34 | * @return the default value
35 | */
36 | String defaultValue() default Constants.DEFAULT_VALUE;
37 |
38 | /**
39 | * Description of the attribute. Works best in the documentation if it starts with a capital letter and ends with period.
40 | *
41 | * @return the description
42 | */
43 | String description();
44 |
45 | /**
46 | * Whether the attribute is mandatory or optional
47 | *
48 | * @return true if the attribute is required, false otherwise
49 | */
50 | boolean required() default false;
51 | }
52 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/LoadBalancerAttributes.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Annotation used to define arrays of {@link LoadBalancerAttribute}.
10 | */
11 | @Retention(RetentionPolicy.RUNTIME)
12 | @Target(ElementType.TYPE)
13 | public @interface LoadBalancerAttributes {
14 | /**
15 | * @return the array of {@link LoadBalancerAttribute}, must not contain {@code null}.
16 | */
17 | LoadBalancerAttribute[] value();
18 | }
19 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/LoadBalancerType.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import static java.lang.annotation.ElementType.TYPE;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | /**
10 | * The type of the load balancer. Use this annotation on your {@link io.smallrye.stork.spi.LoadBalancerProvider}
11 | *
12 | * The type is used to determine load balancer for services.
13 | *
14 | * Use {@code stork..load-balancer.type=my-load-balancer} to use a
15 | * {@link io.smallrye.stork.spi.LoadBalancerProvider} annotated with {@code @LoadBalancerType("my-load-balancer")}
16 | */
17 | @Retention(RetentionPolicy.RUNTIME)
18 | @Target(TYPE)
19 | public @interface LoadBalancerType {
20 | /**
21 | *
22 | * @return the type of the load balance
23 | */
24 | String value();
25 | }
26 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ServiceConfig.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | /**
4 | * Service configuration, wraps (optional) LoadBalancer configuration, (required) ServiceDiscovery configuration and (optional)
5 | * ServiceRegistrar configuration
6 | * for a single service
7 | */
8 | public interface ServiceConfig {
9 | /**
10 | *
11 | * @return (required) name of the service
12 | */
13 | String serviceName();
14 |
15 | /**
16 | * LoadBalancer configuration or null if the service is meant only to only be mapped to a list of services
17 | *
18 | * @return (optional) load balancer configuration
19 | */
20 | ConfigWithType loadBalancer();
21 |
22 | /**
23 | * ServiceDiscovery configuration for the service
24 | *
25 | * @return (required) service discovery configuration
26 | */
27 | ConfigWithType serviceDiscovery();
28 |
29 | /**
30 | * ServiceRegistrar configuration for the service
31 | *
32 | * @return (required) service registrar configuration
33 | */
34 | ConfigWithType serviceRegistrar();
35 |
36 | /**
37 | * Whether the communication should use a secure connection (e.g. HTTPS)
38 | *
39 | * @return true if SSL, TLS, etc. should be used for the communication
40 | * @deprecated Use the service discovery 'secure' attribute instead
41 | */
42 | @Deprecated
43 | default boolean secure() {
44 | return false;
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ServiceDiscoveryAttribute.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import static java.lang.annotation.ElementType.TYPE;
4 |
5 | import java.lang.annotation.Repeatable;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | /**
11 | * Defines an attribute for a service discovery.
12 | *
13 | * The name of the attribute corresponds to the value used in the configuration, e.g. for name {@code my-attribute},
14 | * use the following to set the value:
15 | * {@code stork..service-discovery.my-attribute}
16 | *
17 | * In the configuration class generated for the service discovery, this attribute will be exposed through
18 | * {@code getMyAttribute()}
19 | */
20 | @Retention(RetentionPolicy.RUNTIME)
21 | @Target(TYPE)
22 | @Repeatable(ServiceDiscoveryAttributes.class)
23 | public @interface ServiceDiscoveryAttribute {
24 | /**
25 | * Attribute name as used in the configuration. Exposed through a getter with name converted to camelCase with
26 | * characters that cannot be used in a java identifiers filtered out.
27 | *
28 | * @return the name of the configuration property
29 | */
30 | String name();
31 |
32 | /**
33 | * Default value for the attribute. If not provided and user didn't set the value - null will be passed
34 | *
35 | * @return the default value
36 | */
37 | String defaultValue() default Constants.DEFAULT_VALUE;
38 |
39 | /**
40 | * Description of the attribute. Works best in the documentation if it starts with a capital letter and ends with period.
41 | *
42 | * @return the description
43 | */
44 | String description();
45 |
46 | /**
47 | * Whether the attribute is mandatory or optional
48 | *
49 | * @return true if the attribute is required, false otherwise
50 | */
51 | boolean required() default false;
52 | }
53 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ServiceDiscoveryAttributes.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Annotation used to define arrays of {@link ServiceDiscoveryAttribute}.
10 | */
11 | @Retention(RetentionPolicy.RUNTIME)
12 | @Target(ElementType.TYPE)
13 | public @interface ServiceDiscoveryAttributes {
14 | /**
15 | * @return the array of {@link ServiceDiscoveryAttribute}, must not contain {@code null}.
16 | */
17 | ServiceDiscoveryAttribute[] value();
18 | }
19 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ServiceDiscoveryType.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import static java.lang.annotation.ElementType.TYPE;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | /**
10 | * The type of the service discovery. Use this annotation on your {@link io.smallrye.stork.spi.ServiceDiscoveryProvider}
11 | *
12 | * The type is used to determine service discovery for services.
13 | *
14 | * Use {@code stork..service-discovery.type=my-service-discovery} to use a
15 | * {@link io.smallrye.stork.spi.ServiceDiscoveryProvider} annotated with {@code @ServiceDiscoveryType("my-service-discovery")}
16 | */
17 | @Retention(RetentionPolicy.RUNTIME)
18 | @Target(TYPE)
19 | public @interface ServiceDiscoveryType {
20 | /**
21 | *
22 | * @return the type of the service discovery
23 | */
24 | String value();
25 | }
26 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ServiceRegistrarAttribute.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import static java.lang.annotation.ElementType.TYPE;
4 |
5 | import java.lang.annotation.Repeatable;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | /**
11 | * Defines an attribute for a service registrar.
12 | *
13 | * The name of the attribute corresponds to the value used in the configuration, e.g. for name {@code my-attribute},
14 | * use the following to set the value:
15 | * {@code stork-registrar..my-attribute}
16 | *
17 | * In the configuration class generated for the service registrar, this attribute will be exposed through
18 | * {@code getMyAttribute()}
19 | */
20 | @Retention(RetentionPolicy.RUNTIME)
21 | @Target(TYPE)
22 | @Repeatable(ServiceRegistrarAttributes.class)
23 | public @interface ServiceRegistrarAttribute {
24 | /**
25 | * Attribute name as used in the configuration. Exposed through a getter with name converted to camelCase with
26 | * characters that cannot be used in a java identifiers filtered out.
27 | *
28 | * @return the name of the configuration property
29 | */
30 | String name();
31 |
32 | /**
33 | * Default value for the attribute. If not provided and user didn't set the value - null will be passed
34 | *
35 | * @return the default value
36 | */
37 | String defaultValue() default Constants.DEFAULT_VALUE;
38 |
39 | /**
40 | * Description of the attribute. Works best in the documentation if it starts with a capital letter and ends with period.
41 | *
42 | * @return the description
43 | */
44 | String description();
45 |
46 | /**
47 | * Whether the attribute is mandatory or optional
48 | *
49 | * @return true if the attribute is required, false otherwise
50 | */
51 | boolean required() default false;
52 | }
53 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ServiceRegistrarAttributes.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Annotation used to define arrays of {@link ServiceRegistrarAttribute}.
10 | */
11 | @Retention(RetentionPolicy.RUNTIME)
12 | @Target(ElementType.TYPE)
13 | public @interface ServiceRegistrarAttributes {
14 | /**
15 | * @return the array of {@link ServiceRegistrarAttribute}, must not contain {@code null}.
16 | */
17 | ServiceRegistrarAttribute[] value();
18 | }
19 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ServiceRegistrarConfig.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | public interface ServiceRegistrarConfig extends ConfigWithType {
4 | String name();
5 | }
6 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/config/ServiceRegistrarType.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.config;
2 |
3 | import static java.lang.annotation.ElementType.TYPE;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import io.smallrye.stork.api.MetadataKey;
10 | import io.smallrye.stork.spi.ServiceRegistrarProvider;
11 |
12 | /**
13 | * The type of the service registrar. Use this annotation on your {@link ServiceRegistrarProvider}
14 | *
15 | * The type is used to determine service registrar.
16 | *
17 | * Use {@code stork.my-registration.service-registrar.type=my-service-registrar} to use the
18 | * {@link ServiceRegistrarProvider} annotated with {@code @ServiceRegistrar("my-service-registrar")}
19 | */
20 | @Retention(RetentionPolicy.RUNTIME)
21 | @Target(TYPE)
22 | public @interface ServiceRegistrarType {
23 | /**
24 | * @return the type of the service registrar
25 | */
26 | String value();
27 |
28 | /**
29 | * @return metadata key type for the service registrar. Must match the second type argument of the service registrar
30 | * provider
31 | */
32 | Class extends MetadataKey> metadataKey();
33 | }
34 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/observability/NoopObservationCollector.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.observability;
2 |
3 | import java.util.List;
4 |
5 | import io.smallrye.stork.api.ServiceInstance;
6 |
7 | public class NoopObservationCollector implements ObservationCollector {
8 |
9 | private static final StorkEventHandler NOOP_HANDLER = ev -> {
10 | // NOOP
11 | };
12 |
13 | public static final StorkObservation NOOP_STORK_EVENT = new StorkObservation(
14 | null, null,
15 | null, NOOP_HANDLER) {
16 | @Override
17 | public void onServiceDiscoverySuccess(List instances) {
18 | // Noop
19 | }
20 |
21 | @Override
22 | public void onServiceDiscoveryFailure(Throwable throwable) {
23 | // Noop
24 | }
25 |
26 | @Override
27 | public void onServiceSelectionSuccess(long id) {
28 | // Noop
29 | }
30 |
31 | @Override
32 | public void onServiceSelectionFailure(Throwable throwable) {
33 | // Noop
34 | }
35 | };
36 |
37 | @Override
38 | public StorkObservation create(String serviceName, String serviceDiscoveryType,
39 | String serviceSelectionType) {
40 | return NOOP_STORK_EVENT;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/observability/ObservationCollector.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.observability;
2 |
3 | public interface ObservationCollector {
4 |
5 | StorkObservation create(String serviceName, String serviceDiscoveryType, String serviceSelectionType);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/api/observability/StorkEventHandler.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api.observability;
2 |
3 | public interface StorkEventHandler {
4 | void complete(StorkObservation event);
5 | }
6 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/CallStatisticsCollector.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi;
2 |
3 | /**
4 | * If you use {@code ServiceInstanceWithStatGathering}, use an implementation of this class interface
5 | * for actually collecting information about calls made
6 | */
7 | public interface CallStatisticsCollector {
8 |
9 | /**
10 | * Records the start of an operation.
11 | *
12 | * @param serviceInstanceId the service instance id
13 | * @param measureTime whether the time must be measured
14 | */
15 | default void recordStart(long serviceInstanceId, boolean measureTime) {
16 | }
17 |
18 | /**
19 | * Records the response from an operation.
20 | *
21 | * @param serviceInstanceId the service instance id
22 | * @param timeInNanos the duration of the operation in nanoseconds
23 | */
24 | default void recordReply(long serviceInstanceId, long timeInNanos) {
25 |
26 | }
27 |
28 | /**
29 | * Records the completion of an operation.
30 | *
31 | * @param serviceInstanceId the service instance id
32 | * @param error the error thrown by the operation if the operation failed
33 | */
34 | default void recordEnd(long serviceInstanceId, Throwable error) {
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/ElementWithType.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi;
2 |
3 | /**
4 | * A class having a {@link #type()} method such a load balancer and service discovery providers.
5 | */
6 | public interface ElementWithType {
7 | /**
8 | * Gets the type.
9 | *
10 | * @return the type, must not be {@code null}, must not be blank
11 | */
12 | String type();
13 | }
14 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/LoadBalancerProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi;
2 |
3 | import io.smallrye.stork.api.LoadBalancer;
4 | import io.smallrye.stork.api.ServiceDiscovery;
5 |
6 | /**
7 | * A load balancer provider allowing to create instances of load balancers.
8 | *
9 | * Implementation should use the {@link io.smallrye.stork.api.config.LoadBalancerAttribute} to define attributes.
10 | *
11 | * @param the configuration type (class generated from the {@link io.smallrye.stork.api.config.LoadBalancerAttribute}
12 | * annotations).
13 | */
14 | public interface LoadBalancerProvider {
15 | /**
16 | * Creates a load balancer instance
17 | *
18 | * @param config the configuration
19 | * @param serviceDiscovery the service discovery used for that service
20 | * @return the load balancer
21 | */
22 | LoadBalancer createLoadBalancer(T config, ServiceDiscovery serviceDiscovery);
23 | }
24 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/ServiceDiscoveryProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi;
2 |
3 | import io.smallrye.stork.api.ServiceDiscovery;
4 | import io.smallrye.stork.api.config.ServiceConfig;
5 |
6 | /**
7 | * A service discovery provider allowing to create instances of service discovery.
8 | *
9 | * Implementation should use the {@link io.smallrye.stork.api.config.ServiceDiscoveryAttribute} to define attributes.
10 | *
11 | * @param the configuration type (class generated from the {@link io.smallrye.stork.api.config.ServiceDiscoveryAttribute}
12 | * annotations).
13 | */
14 | public interface ServiceDiscoveryProvider {
15 |
16 | /**
17 | * Creates a new instance of {@link ServiceDiscovery}.
18 | *
19 | * @param config the configuration, must not be {@code null}
20 | * @param serviceName the service name, must not be {@code null}, or blank.
21 | * @param serviceConfig the service config, must not be {@code null}
22 | * @param storkInfrastructure the stork infrastructure, must not be {@code null}
23 | * @return the service discovery instance
24 | */
25 | ServiceDiscovery createServiceDiscovery(T config, String serviceName,
26 | ServiceConfig serviceConfig, StorkInfrastructure storkInfrastructure);
27 | }
28 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/ServiceRegistrarProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi;
2 |
3 | import io.smallrye.stork.api.MetadataKey;
4 | import io.smallrye.stork.api.ServiceRegistrar;
5 |
6 | public interface ServiceRegistrarProvider & MetadataKey> {
7 | ServiceRegistrar createServiceRegistrar(T config, String serviceRegistrarName,
8 | StorkInfrastructure infrastructure);
9 | }
10 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/StorkInfrastructure.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi;
2 |
3 | import java.util.function.Supplier;
4 |
5 | import io.smallrye.stork.api.observability.NoopObservationCollector;
6 | import io.smallrye.stork.api.observability.ObservationCollector;
7 |
8 | /**
9 | * A provider for "utility" objects used by service discovery and load balancer implementations.
10 | *
11 | * The default implementation, {@code DefaultStorkInfrastructure} provides objects created by the passed supplier.
12 | * Vendors can implement their own version of this class to provide custom objects.
13 | *
14 | * E.g. Quarkus uses a single Vert.x instance throughout the project and overrides this to return this Vert.x instance
15 | */
16 | public interface StorkInfrastructure {
17 | /**
18 | * Get an instance of a "utility" class
19 | *
20 | * @param utilityClass class of the requested object
21 | * @param defaultSupplier should be used by the implementation to create an object if the environment doesn't provide one,
22 | * the result value can be cached.
23 | * @param type of the utility object
24 | *
25 | * @return the utility object
26 | *
27 | * @throws NullPointerException if utilityClass or defaultSupplier are null
28 | */
29 | T get(Class utilityClass, Supplier defaultSupplier);
30 |
31 | default ObservationCollector getObservationCollector() {
32 | return new NoopObservationCollector();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/config/ConfigProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi.config;
2 |
3 | import java.util.List;
4 |
5 | import io.smallrye.stork.api.config.ServiceConfig;
6 |
7 | /**
8 | * Configuration provider for Service Discovery and Load Balancer
9 | */
10 | public interface ConfigProvider {
11 | /**
12 | * Get a list of service configurations, each wrapping a configuration for both
13 | * ServiceDiscovery and LoadBalancer
14 | *
15 | * @return a list of configurations
16 | */
17 | List getConfigs();
18 |
19 | /**
20 | * Priority of the configuration provider.
21 | * A single ConfigProvider is used in an application, the one with the highest priority
22 | *
23 | * @return the priority
24 | */
25 | int priority();
26 | }
27 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/config/SimpleRegistrarConfig.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi.config;
2 |
3 | import java.util.Map;
4 |
5 | import io.smallrye.stork.api.config.ServiceRegistrarConfig;
6 |
7 | public class SimpleRegistrarConfig implements ServiceRegistrarConfig {
8 | private final String type;
9 | private final String name;
10 | private final Map parameters;
11 |
12 | public SimpleRegistrarConfig(String type, String name, Map parameters) {
13 | this.type = type;
14 | this.name = name;
15 | this.parameters = parameters;
16 | }
17 |
18 | @Override
19 | public String type() {
20 | return type;
21 | }
22 |
23 | @Override
24 | public Map parameters() {
25 | return parameters;
26 | }
27 |
28 | @Override
29 | public String name() {
30 | return name;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/internal/LoadBalancerLoader.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi.internal;
2 |
3 | import io.smallrye.stork.api.LoadBalancer;
4 | import io.smallrye.stork.api.ServiceDiscovery;
5 | import io.smallrye.stork.api.config.ConfigWithType;
6 | import io.smallrye.stork.spi.ElementWithType;
7 |
8 | /**
9 | * Used by stork internals to generate service loader for LoadBalancerProvider
10 | */
11 | public interface LoadBalancerLoader extends ElementWithType {
12 | /**
13 | * Creates a load balancer instance.
14 | *
15 | * @param config the configuration, must not be {@code null}
16 | * @param serviceDiscovery the service discovery used for that service
17 | * @return the load balancer
18 | */
19 | LoadBalancer createLoadBalancer(ConfigWithType config, ServiceDiscovery serviceDiscovery);
20 | }
21 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/internal/ServiceDiscoveryLoader.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi.internal;
2 |
3 | import io.smallrye.stork.api.ServiceDiscovery;
4 | import io.smallrye.stork.api.config.ConfigWithType;
5 | import io.smallrye.stork.api.config.ServiceConfig;
6 | import io.smallrye.stork.spi.ElementWithType;
7 | import io.smallrye.stork.spi.StorkInfrastructure;
8 |
9 | /**
10 | * Used by stork internals to generate service loader for ServiceDiscoveryProvider.
11 | */
12 | public interface ServiceDiscoveryLoader extends ElementWithType {
13 |
14 | /**
15 | * Creates a new {@link ServiceDiscovery} instance.
16 | *
17 | * @param config the service discovery configuration, must not be {@code null}
18 | * @param serviceName the service name, must not be {@code null} or blank
19 | * @param serviceConfig the service configuration, must not be {@code null}
20 | * @param storkInfrastructure the stork infrastructure, must not be {@code null}
21 | * @return the new {@link ServiceDiscovery}
22 | */
23 | ServiceDiscovery createServiceDiscovery(ConfigWithType config, String serviceName,
24 | ServiceConfig serviceConfig, StorkInfrastructure storkInfrastructure);
25 | }
26 |
--------------------------------------------------------------------------------
/api/src/main/java/io/smallrye/stork/spi/internal/ServiceRegistrarLoader.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.spi.internal;
2 |
3 | import io.smallrye.stork.api.MetadataKey;
4 | import io.smallrye.stork.api.ServiceRegistrar;
5 | import io.smallrye.stork.api.config.ConfigWithType;
6 | import io.smallrye.stork.spi.ElementWithType;
7 | import io.smallrye.stork.spi.StorkInfrastructure;
8 |
9 | /**
10 | * Used by stork internals to generate service loader for ServiceRegistrarProvider.
11 | */
12 | public interface ServiceRegistrarLoader & MetadataKey> extends ElementWithType {
13 |
14 | /**
15 | * Creates a new {@link ServiceRegistrar} instance.
16 | *
17 | * @param config the service registrar configuration, must not be {@code null}
18 | * @param serviceName
19 | * @param storkInfrastructure the stork infrastructure, must not be {@code null}
20 | * @return the new {@link ServiceRegistrar}
21 | */
22 | ServiceRegistrar createServiceRegistrar(ConfigWithType config,
23 | String serviceName, StorkInfrastructure storkInfrastructure);
24 | }
25 |
--------------------------------------------------------------------------------
/api/src/test/java/io/smallrye/stork/api/NoAcceptableServiceInstanceFoundExceptionTest.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.api.Test;
5 |
6 | class NoAcceptableServiceInstanceFoundExceptionTest {
7 |
8 | @Test
9 | void canCreateNoAcceptableServiceInstanceFoundException() {
10 | NoAcceptableServiceInstanceFoundException exception = new NoAcceptableServiceInstanceFoundException("missing");
11 | Assertions.assertEquals("missing", exception.getMessage());
12 | Assertions.assertNull(exception.getCause());
13 |
14 | Exception cause = new ArithmeticException("boom");
15 | exception = new NoAcceptableServiceInstanceFoundException("missing", cause);
16 | Assertions.assertEquals("missing", exception.getMessage());
17 | Assertions.assertEquals(cause, exception.getCause());
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/api/src/test/java/io/smallrye/stork/api/NoServiceInstanceFoundExceptionTest.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.api.Test;
5 |
6 | class NoServiceInstanceFoundExceptionTest {
7 |
8 | @Test
9 | void canCreateNoServiceInstanceFoundException() {
10 | NoServiceInstanceFoundException exception = new NoServiceInstanceFoundException("missing");
11 | Assertions.assertEquals("missing", exception.getMessage());
12 | Assertions.assertNull(exception.getCause());
13 |
14 | Exception cause = new ArithmeticException("boom");
15 | exception = new NoServiceInstanceFoundException("missing", cause);
16 | Assertions.assertEquals("missing", exception.getMessage());
17 | Assertions.assertEquals(cause, exception.getCause());
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/api/src/test/java/io/smallrye/stork/api/ServiceInstanceTest.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.api;
2 |
3 | import java.util.Map;
4 | import java.util.Optional;
5 |
6 | import org.junit.jupiter.api.Assertions;
7 | import org.junit.jupiter.api.Test;
8 |
9 | /**
10 | * Verify the default implementation for {@link ServiceInstance}.
11 | */
12 | class ServiceInstanceTest {
13 |
14 | ServiceInstance instance = new ServiceInstance() {
15 | @Override
16 | public long getId() {
17 | return 0;
18 | }
19 |
20 | @Override
21 | public String getHost() {
22 | return null;
23 | }
24 |
25 | @Override
26 | public int getPort() {
27 | return 0;
28 | }
29 |
30 | @Override
31 | public Optional getPath() {
32 | return Optional.empty();
33 | }
34 |
35 | @Override
36 | public boolean isSecure() {
37 | return false;
38 | }
39 | };
40 |
41 | @Test
42 | void defaultMetadataShouldBeEmpty() {
43 | Metadata> metadata = instance.getMetadata();
44 | Assertions.assertNotNull(metadata);
45 | Assertions.assertNull(metadata.getMetadata().get("foo"));
46 | }
47 |
48 | @Test
49 | void defaultLabelsShouldBeEmpty() {
50 | Map labels = instance.getLabels();
51 | Assertions.assertNotNull(labels);
52 | Assertions.assertTrue(labels.isEmpty());
53 | }
54 |
55 | @Test
56 | void defaultStatisticsAreDisabled() {
57 | Assertions.assertFalse(instance.gatherStatistics());
58 | Assertions.assertDoesNotThrow(() -> instance.recordStart(true));
59 | Assertions.assertDoesNotThrow(() -> instance.recordReply());
60 | Assertions.assertDoesNotThrow(() -> instance.recordEnd(null));
61 | Assertions.assertDoesNotThrow(() -> instance.recordStart(false));
62 | Assertions.assertDoesNotThrow(() -> instance.recordEnd(new Exception("boom")));
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/config-generator/src/main/java/io/smallrye/stork/config/generator/ClassName.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.config.generator;
2 |
3 | public class ClassName {
4 | public final String fullName;
5 | public final String simpleName;
6 |
7 | public ClassName(String fullName, String simpleName) {
8 | this.fullName = fullName;
9 | this.simpleName = simpleName;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/core/revapi.json:
--------------------------------------------------------------------------------
1 | [ {
2 | "extension" : "revapi.java",
3 | "id" : "java",
4 | "configuration" : {
5 | "missing-classes" : {
6 | "behavior" : "report",
7 | "ignoreMissingAnnotations" : false
8 | }
9 | }
10 | }, {
11 | "extension" : "revapi.filter",
12 | "configuration" : {
13 | "elements" : {
14 | "include" : [ {
15 | "matcher" : "java-package",
16 | "match" : "/io\\.smallrye\\.stork/"
17 | }, {
18 | "matcher" : "java-package",
19 | "match" : "/io\\.smallrye\\.stork\\.integration(\\..*)?/"
20 | }, {
21 | "matcher" : "java-package",
22 | "match" : "/io\\.smallrye\\.stork\\.utils(\\..*)?/"
23 | } ],
24 | "exclude" : [ "class io\\.smallrye\\.stork\\.impl\\..*" ]
25 | }
26 | }
27 | }, {
28 | "extension" : "revapi.differences",
29 | "id" : "breaking-changes",
30 | "configuration" : {
31 | "criticality" : "highlight",
32 | "minSeverity" : "POTENTIALLY_BREAKING",
33 | "minCriticality" : "documented",
34 | "differences" : [ ]
35 | }
36 | }, {
37 | "extension" : "revapi.reporter.json",
38 | "configuration" : {
39 | "minSeverity" : "POTENTIALLY_BREAKING",
40 | "minCriticality" : "documented",
41 | "output" : "target/compatibility.json",
42 | "indent" : true,
43 | "append" : false,
44 | "keepEmptyFile" : true
45 | }
46 | }, {
47 | "extension" : "revapi.reporter.text",
48 | "configuration" : {
49 | "minSeverity" : "POTENTIALLY_BREAKING",
50 | "minCriticality" : "documented",
51 | "output" : "out"
52 | }
53 | } ]
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/impl/ConsulMetadataKey.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.impl;
2 |
3 | import io.smallrye.stork.api.MetadataKey;
4 |
5 | /**
6 | * The Consul metadata keys.
7 | */
8 | public enum ConsulMetadataKey implements MetadataKey {
9 |
10 | /**
11 | * The key for the consul service id.
12 | */
13 | META_CONSUL_SERVICE_ID("consul-service-id"),
14 | /**
15 | * The key for the consul service node.
16 | */
17 | META_CONSUL_SERVICE_NODE("consul-service-node"),
18 | /**
19 | * The key for the consul service node address.
20 | */
21 | META_CONSUL_SERVICE_NODE_ADDRESS("consul-service-node-address");
22 |
23 | private final String name;
24 |
25 | /**
26 | * Creates a new ConsulMetadataKey
27 | *
28 | * @param name the name
29 | */
30 | ConsulMetadataKey(String name) {
31 | this.name = name;
32 | }
33 |
34 | @Override
35 | public String getName() {
36 | return name;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/impl/EurekaMetadataKey.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.impl;
2 |
3 | import io.smallrye.stork.api.MetadataKey;
4 |
5 | /**
6 | * The Eureka metadata keys.
7 | */
8 | public enum EurekaMetadataKey implements MetadataKey {
9 |
10 | /**
11 | * The key for the eureka service id.
12 | */
13 | META_EUREKA_SERVICE_ID("eureka-service-id");
14 |
15 | private final String name;
16 |
17 | /**
18 | * Creates a new ConsulMetadataKey
19 | *
20 | * @param name the name
21 | */
22 | EurekaMetadataKey(String name) {
23 | this.name = name;
24 | }
25 |
26 | @Override
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/impl/RoundRobinLoadBalancer.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.impl;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.Comparator;
6 | import java.util.List;
7 | import java.util.concurrent.atomic.AtomicInteger;
8 |
9 | import io.smallrye.stork.api.LoadBalancer;
10 | import io.smallrye.stork.api.NoServiceInstanceFoundException;
11 | import io.smallrye.stork.api.ServiceInstance;
12 |
13 | public class RoundRobinLoadBalancer implements LoadBalancer {
14 |
15 | private final AtomicInteger index = new AtomicInteger();
16 |
17 | @Override
18 | public ServiceInstance selectServiceInstance(Collection serviceInstances) {
19 | if (serviceInstances.isEmpty()) {
20 | throw new NoServiceInstanceFoundException("No services found.");
21 | }
22 | // todo do better, cache the list if possible maybe?
23 | List modifiableList = new ArrayList<>(serviceInstances);
24 | modifiableList.sort(Comparator.comparingLong(ServiceInstance::getId));
25 | return select(modifiableList);
26 | }
27 |
28 | @Override
29 | public boolean requiresStrictRecording() {
30 | return false;
31 | }
32 |
33 | private ServiceInstance select(List instances) {
34 | if (instances.isEmpty()) {
35 | return null;
36 | }
37 |
38 | return instances.get(index.getAndIncrement() % instances.size());
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/impl/RoundRobinLoadBalancerProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.impl;
2 |
3 | import io.smallrye.stork.Stork;
4 | import io.smallrye.stork.api.LoadBalancer;
5 | import io.smallrye.stork.api.ServiceDiscovery;
6 | import io.smallrye.stork.api.config.LoadBalancerType;
7 | import io.smallrye.stork.spi.LoadBalancerProvider;
8 |
9 | /**
10 | * Round-robin is the only implementation built-in in the Stork API.
11 | * It is used when no load-balancer configuration is given.
12 | *
13 | * Note that it is not registered using the SPI, but directly in {@link Stork#initialize()}.
14 | */
15 | @LoadBalancerType(RoundRobinLoadBalancerProvider.ROUND_ROBIN_TYPE)
16 | public class RoundRobinLoadBalancerProvider
17 | implements LoadBalancerProvider {
18 |
19 | public static final String ROUND_ROBIN_TYPE = "round-robin";
20 |
21 | @Override
22 | public LoadBalancer createLoadBalancer(io.smallrye.stork.impl.RoundRobinConfiguration config,
23 | ServiceDiscovery serviceDiscovery) {
24 | return new RoundRobinLoadBalancer();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/impl/ServiceInstanceWithStatGathering.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.impl;
2 |
3 | import java.util.Optional;
4 |
5 | import io.smallrye.stork.api.ServiceInstance;
6 | import io.smallrye.stork.spi.CallStatisticsCollector;
7 |
8 | public class ServiceInstanceWithStatGathering implements ServiceInstance {
9 | private final ServiceInstance delegate;
10 | private final CallStatisticsCollector statistics;
11 |
12 | volatile long start;
13 |
14 | public ServiceInstanceWithStatGathering(ServiceInstance delegate, CallStatisticsCollector statistics) {
15 | this.delegate = delegate;
16 | this.statistics = statistics;
17 | }
18 |
19 | @Override
20 | public boolean gatherStatistics() {
21 | return true;
22 | }
23 |
24 | @Override
25 | public long getId() {
26 | return delegate.getId();
27 | }
28 |
29 | @Override
30 | public String getHost() {
31 | return delegate.getHost();
32 | }
33 |
34 | @Override
35 | public int getPort() {
36 | return delegate.getPort();
37 | }
38 |
39 | @Override
40 | public Optional getPath() {
41 | return delegate.getPath();
42 | }
43 |
44 | @Override
45 | public boolean isSecure() {
46 | return delegate.isSecure();
47 | }
48 |
49 | @Override
50 | public void recordStart(boolean measureTime) {
51 | if (measureTime) {
52 | start = System.nanoTime();
53 | }
54 | statistics.recordStart(getId(), measureTime);
55 | }
56 |
57 | @Override
58 | public void recordReply() {
59 | statistics.recordReply(getId(), System.nanoTime() - start);
60 | }
61 |
62 | @Override
63 | public void recordEnd(Throwable failure) {
64 | statistics.recordEnd(getId(), failure);
65 | }
66 |
67 | /**
68 | * Do not use for production code
69 | *
70 | * mock recording time for tests
71 | *
72 | * @param timeInNs time to record, in nanoseconds
73 | */
74 | @Deprecated //for tests only
75 | public void mockRecordingTime(long timeInNs) {
76 | statistics.recordReply(getId(), timeInNs);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/integration/DefaultStorkInfrastructure.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.integration;
2 |
3 | import java.util.Map;
4 | import java.util.Objects;
5 | import java.util.concurrent.ConcurrentHashMap;
6 | import java.util.function.Supplier;
7 |
8 | import io.smallrye.stork.spi.StorkInfrastructure;
9 |
10 | /**
11 | * An implementation of {@link StorkInfrastructure} that creates utility objects from {@code defaultSupplier}
12 | * and caches them
13 | */
14 | public class DefaultStorkInfrastructure implements StorkInfrastructure {
15 | private final Map, Object> utilities = new ConcurrentHashMap<>();
16 |
17 | @SuppressWarnings("unchecked")
18 | @Override
19 | public T get(Class utilityClass, Supplier defaultSupplier) {
20 | Objects.requireNonNull(utilityClass, "utilityClass cannot be null");
21 | Objects.requireNonNull(defaultSupplier, "defaultSupplier cannot be null");
22 | return (T) utilities.computeIfAbsent(utilityClass, key -> defaultSupplier.get());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/integration/ObservableStorkInfrastructure.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.integration;
2 |
3 | import io.smallrye.stork.api.observability.ObservationCollector;
4 |
5 | public class ObservableStorkInfrastructure extends DefaultStorkInfrastructure {
6 |
7 | private final ObservationCollector observationCollector;
8 |
9 | public ObservableStorkInfrastructure(ObservationCollector observationCollector) {
10 | this.observationCollector = observationCollector;
11 | }
12 |
13 | @Override
14 | public ObservationCollector getObservationCollector() {
15 | return observationCollector;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/utils/DurationUtils.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.utils;
2 |
3 | import java.time.Duration;
4 | import java.util.regex.Pattern;
5 |
6 | /**
7 | * A set of utility methods around durations.
8 | */
9 | public class DurationUtils {
10 |
11 | private static final Pattern DIGITS = Pattern.compile("^[-+]?\\d+$");
12 |
13 | private DurationUtils() {
14 | // Avoid direct instantiation
15 | }
16 |
17 | /**
18 | * Converts a value representing the refresh period which start with a number by implicitly appending `PT` to it.
19 | * If the value consists only of a number, it implicitly treats the value as seconds.
20 | * Otherwise, tries to convert the value assuming that it is in the accepted ISO-8601 duration format.
21 | *
22 | * @param duration duration as String
23 | * @param parameter the parameter for which we parse the value to duration
24 | * @return {@link Duration}
25 | */
26 | public static Duration parseDuration(String duration, String parameter) {
27 | if (duration.startsWith("-")) {
28 | throw new IllegalArgumentException("Negative " + parameter + " specified for service discovery: " + duration);
29 | }
30 | if (DIGITS.asPredicate().test(duration)) {
31 | return Duration.ofSeconds(Long.parseLong(duration));
32 | }
33 | return Duration.parse("PT" + duration);
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/utils/HostAndPort.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.utils;
2 |
3 | import java.util.Optional;
4 |
5 | /**
6 | * Structure representing a host:port address.
7 | */
8 | @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
9 | public class HostAndPort {
10 | /**
11 | * The host.
12 | */
13 | public final String host;
14 | /**
15 | * The port.
16 | */
17 | public final int port;
18 |
19 | /**
20 | * The path, if any.
21 | */
22 | public final Optional path;
23 |
24 | /**
25 | * Creates a new HostAndPort
26 | *
27 | * @param host the host
28 | * @param port the port
29 | * @param path the path, can be {@code null}
30 | */
31 | public HostAndPort(String host, int port, String path) {
32 | this.host = host;
33 | this.port = port;
34 | this.path = Optional.ofNullable(path);
35 | }
36 |
37 | /**
38 | * Creates a new HostAndPort
39 | *
40 | * @param host the host
41 | * @param port the port
42 | */
43 | public HostAndPort(String host, int port) {
44 | this(host, port, null);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/utils/InMemoryAddressesBackend.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.utils;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | public class InMemoryAddressesBackend {
9 |
10 | private static Map> backend = new HashMap<>();
11 |
12 | public static List getAddresses(String serviceName) {
13 | return backend.get(serviceName);
14 | }
15 |
16 | public static void add(String serviceName, String address) {
17 | if (serviceName == null || serviceName.length() == 0) {
18 | throw new IllegalArgumentException("No service name provided for address " + address);
19 | }
20 | if (backend.get(serviceName) != null) {
21 | if (!backend.get(serviceName).contains(address)) {
22 | backend.get(serviceName).add(address);
23 | }
24 | } else {
25 | List addresses = new ArrayList<>();
26 | addresses.add(address);
27 | backend.put(serviceName, addresses);
28 | }
29 | }
30 |
31 | public static void clear(String serviceName) {
32 | if (backend != null) {
33 | backend.remove(serviceName);
34 | }
35 | }
36 |
37 | public static void clearAll() {
38 | backend.clear();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/utils/ServiceInstanceIds.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.utils;
2 |
3 | import java.util.concurrent.atomic.AtomicLong;
4 |
5 | /**
6 | * Service instance id generator.
7 | */
8 | // TODO: is this sufficient?
9 | public class ServiceInstanceIds {
10 |
11 | private static final AtomicLong idSequence = new AtomicLong();
12 |
13 | /**
14 | * Gets the next, unused instance id.
15 | *
16 | * @return the next instance id
17 | */
18 | public static Long next() {
19 | return idSequence.getAndIncrement();
20 | }
21 |
22 | private ServiceInstanceIds() {
23 | // Avoid direct instantiation
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/core/src/main/java/io/smallrye/stork/utils/ServiceInstanceUtils.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.utils;
2 |
3 | import java.util.Collection;
4 |
5 | import io.smallrye.stork.api.ServiceInstance;
6 |
7 | /**
8 | * A set of utility methods around {@link ServiceInstance}.
9 | */
10 | public class ServiceInstanceUtils {
11 |
12 | /**
13 | * Finds a matching instance for a given hostname and port
14 | *
15 | * @param serviceInstances the list of instances
16 | * @param hostname the hostname
17 | * @param port the port
18 | * @return the found instance or {@code null} if none matches
19 | */
20 | public static ServiceInstance findMatching(Collection serviceInstances, String hostname, int port) {
21 | if (hostname == null) {
22 | throw new NullPointerException("Hostname cannot be null");
23 | }
24 | for (ServiceInstance instance : serviceInstances) {
25 | if (hostname.equals(instance.getHost()) && port == instance.getPort()) {
26 | return instance;
27 | }
28 | }
29 | return null;
30 | }
31 |
32 | private ServiceInstanceUtils() {
33 | // Avoid direct instantiation.
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/core/src/main/resources/META-INF/beans.xml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallrye/smallrye-stork/47751840baa0ae2fadc5e010e186526b86cb2bc6/core/src/main/resources/META-INF/beans.xml
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/EmptyLoadBalancerProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import io.smallrye.stork.api.LoadBalancer;
4 | import io.smallrye.stork.api.ServiceDiscovery;
5 | import io.smallrye.stork.api.config.LoadBalancerType;
6 | import io.smallrye.stork.spi.LoadBalancerProvider;
7 |
8 | @LoadBalancerType("empty-selector")
9 | public class EmptyLoadBalancerProvider implements LoadBalancerProvider {
10 |
11 | @Override
12 | public LoadBalancer createLoadBalancer(EmptySelectorConfiguration config, ServiceDiscovery serviceDiscovery) {
13 | return null;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/EmptyServiceDiscoveryProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import io.smallrye.stork.api.ServiceDiscovery;
4 | import io.smallrye.stork.api.config.ServiceConfig;
5 | import io.smallrye.stork.api.config.ServiceDiscoveryType;
6 | import io.smallrye.stork.spi.ServiceDiscoveryProvider;
7 | import io.smallrye.stork.spi.StorkInfrastructure;
8 |
9 | @ServiceDiscoveryType("empty")
10 | public class EmptyServiceDiscoveryProvider
11 | implements ServiceDiscoveryProvider {
12 |
13 | @Override
14 | public ServiceDiscovery createServiceDiscovery(EmptyConfiguration config, String serviceName,
15 | ServiceConfig serviceConfig, StorkInfrastructure storkInfrastructure) {
16 | return null;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/FakeObservationCollector.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import io.smallrye.stork.api.observability.ObservationCollector;
4 | import io.smallrye.stork.api.observability.StorkEventHandler;
5 | import io.smallrye.stork.api.observability.StorkObservation;
6 |
7 | public class FakeObservationCollector implements ObservationCollector {
8 |
9 | private static final StorkEventHandler FAKE_HANDLER = ev -> {
10 | // FAKE
11 | };
12 |
13 | public static StorkObservation FAKE_STORK_EVENT;
14 |
15 | @Override
16 | public StorkObservation create(String serviceName, String serviceDiscoveryType,
17 | String serviceSelectionType) {
18 | FAKE_STORK_EVENT = new StorkObservation(
19 | serviceName, serviceDiscoveryType, serviceSelectionType,
20 | FAKE_HANDLER);
21 | return FAKE_STORK_EVENT;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/MockLoadBalancerProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import static org.mockito.Mockito.mock;
4 |
5 | import jakarta.enterprise.context.ApplicationScoped;
6 |
7 | import io.smallrye.stork.api.LoadBalancer;
8 | import io.smallrye.stork.api.ServiceDiscovery;
9 | import io.smallrye.stork.api.config.LoadBalancerType;
10 | import io.smallrye.stork.spi.LoadBalancerProvider;
11 |
12 | @LoadBalancerType("fake-selector")
13 | @ApplicationScoped
14 | public class MockLoadBalancerProvider implements LoadBalancerProvider {
15 |
16 | @Override
17 | public LoadBalancer createLoadBalancer(FakeSelectorConfiguration config, ServiceDiscovery serviceDiscovery) {
18 | return mock(LoadBalancer.class);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/MockServiceDiscoveryProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import static org.mockito.Mockito.mock;
4 |
5 | import jakarta.enterprise.context.ApplicationScoped;
6 |
7 | import io.smallrye.stork.api.ServiceDiscovery;
8 | import io.smallrye.stork.api.config.ServiceConfig;
9 | import io.smallrye.stork.api.config.ServiceDiscoveryAttribute;
10 | import io.smallrye.stork.api.config.ServiceDiscoveryType;
11 | import io.smallrye.stork.spi.ServiceDiscoveryProvider;
12 | import io.smallrye.stork.spi.StorkInfrastructure;
13 |
14 | @ServiceDiscoveryType("mock")
15 | @ServiceDiscoveryAttribute(name = "failure", description = "indicates if service discovery should fail")
16 | @ApplicationScoped
17 | public class MockServiceDiscoveryProvider implements ServiceDiscoveryProvider {
18 |
19 | @Override
20 | public ServiceDiscovery createServiceDiscovery(MockConfiguration config, String serviceName, ServiceConfig serviceConfig,
21 | StorkInfrastructure storkInfrastructure) {
22 | return mock(ServiceDiscovery.class);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/MyDataBean.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import jakarta.enterprise.context.ApplicationScoped;
4 |
5 | @ApplicationScoped
6 | public class MyDataBean {
7 |
8 | private String value;
9 |
10 | public void set(String value) {
11 | this.value = value;
12 | }
13 |
14 | public String value() {
15 | return this.value;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/SingleLoadBalancer.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import java.util.Collection;
4 |
5 | import io.smallrye.stork.api.LoadBalancer;
6 | import io.smallrye.stork.api.NoServiceInstanceFoundException;
7 | import io.smallrye.stork.api.ServiceInstance;
8 |
9 | public class SingleLoadBalancer implements LoadBalancer {
10 |
11 | ServiceInstance instance;
12 |
13 | @Override
14 | public ServiceInstance selectServiceInstance(Collection serviceInstances) {
15 |
16 | if (instance == null && !serviceInstances.isEmpty()) {
17 | instance = serviceInstances.iterator().next();
18 | return instance;
19 | }
20 |
21 | if (instance != null) {
22 | return instance;
23 | }
24 |
25 | throw new NoServiceInstanceFoundException("nope");
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/SingleLoadBalancerProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import io.smallrye.stork.api.LoadBalancer;
4 | import io.smallrye.stork.api.ServiceDiscovery;
5 | import io.smallrye.stork.api.config.LoadBalancerType;
6 | import io.smallrye.stork.spi.LoadBalancerProvider;
7 |
8 | @LoadBalancerType("single")
9 |
10 | public class SingleLoadBalancerProvider implements LoadBalancerProvider {
11 | @Override
12 | public LoadBalancer createLoadBalancer(SingleConfiguration config, ServiceDiscovery serviceDiscovery) {
13 | return new SingleLoadBalancer();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/TestEnv.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.io.UncheckedIOException;
6 | import java.nio.file.Files;
7 | import java.nio.file.Path;
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.HashSet;
11 | import java.util.List;
12 | import java.util.Set;
13 | import java.util.stream.Collectors;
14 |
15 | import io.smallrye.stork.api.config.ServiceConfig;
16 | import io.smallrye.stork.spi.config.ConfigProvider;
17 |
18 | public class TestEnv {
19 | public static final File SPI_ROOT = new File("target/test-classes/META-INF/services");
20 | public static final List configurations = new ArrayList<>();
21 | public static Set createdSpis = new HashSet<>();
22 |
23 | @SuppressWarnings("unchecked")
24 | public static void install(Class itf, Class extends T>... impls) {
25 | File out = new File(SPI_ROOT, itf.getName());
26 | if (out.isFile()) {
27 | throw new IllegalArgumentException(out.getAbsolutePath() + " does already exist");
28 | }
29 | if (impls == null || impls.length == 0) {
30 | throw new IllegalArgumentException("The list of providers must not be `null` or empty");
31 | }
32 |
33 | List list = Arrays.stream(impls).map(Class::getName).collect(Collectors.toList());
34 | try {
35 | Files.write(out.toPath(), list);
36 | } catch (IOException e) {
37 | throw new UncheckedIOException(e);
38 | }
39 | createdSpis.add(out.toPath());
40 | }
41 |
42 | public static void clearSPIs() throws IOException {
43 | for (Path createdSpi : createdSpis) {
44 | Files.delete(createdSpi);
45 | }
46 | createdSpis.clear();
47 | }
48 |
49 | public static class AnchoredConfigProvider implements ConfigProvider {
50 |
51 | @Override
52 | public List getConfigs() {
53 | return new ArrayList<>(configurations);
54 | }
55 |
56 | @Override
57 | public int priority() {
58 | return 5;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/TestMetadataKey.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import io.smallrye.stork.api.MetadataKey;
4 |
5 | public enum TestMetadataKey implements MetadataKey {
6 |
7 | /**
8 | * The key for the consul service id.
9 | */
10 | META_CONSUL_SERVICE_ID("consul-service-id"),
11 | /**
12 | * The key for the consul service node.
13 | */
14 | META_CONSUL_SERVICE_NODE("consul-service-node"),
15 | /**
16 | * The key for the consul service node address.
17 | */
18 | META_CONSUL_SERVICE_NODE_ADDRESS("consul-service-node-address");
19 |
20 | private final String name;
21 |
22 | /**
23 | * Creates a new ConsulMetadataKey
24 | *
25 | * @param name the name
26 | */
27 | TestMetadataKey(String name) {
28 | this.name = name;
29 | }
30 |
31 | @Override
32 | public String getName() {
33 | return name;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/TestServiceRegistrar.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import io.smallrye.mutiny.Uni;
7 | import io.smallrye.stork.api.Metadata;
8 | import io.smallrye.stork.api.ServiceRegistrar;
9 | import io.smallrye.stork.spi.StorkInfrastructure;
10 |
11 | public class TestServiceRegistrar implements ServiceRegistrar {
12 | private static final Logger log = LoggerFactory.getLogger(TestServiceRegistrar.class);
13 | private final TestRegistrarConfiguration config;
14 |
15 | public TestServiceRegistrar(TestRegistrarConfiguration config, String serviceName,
16 | StorkInfrastructure infrastructure) {
17 | this.config = config;
18 |
19 | }
20 |
21 | @Override
22 | public Uni registerServiceInstance(String serviceName, Metadata metadata, String ipAddress,
23 | int defaultPort) {
24 | return null;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/TestServiceRegistrarProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import io.smallrye.stork.api.ServiceRegistrar;
4 | import io.smallrye.stork.api.config.ServiceRegistrarType;
5 | import io.smallrye.stork.spi.ServiceRegistrarProvider;
6 | import io.smallrye.stork.spi.StorkInfrastructure;
7 |
8 | @ServiceRegistrarType(value = "test", metadataKey = TestMetadataKey.class)
9 | public class TestServiceRegistrarProvider implements ServiceRegistrarProvider {
10 |
11 | @Override
12 | public ServiceRegistrar createServiceRegistrar(TestRegistrarConfiguration config, String serviceRegistrarName,
13 | StorkInfrastructure infrastructure) {
14 | return new TestServiceRegistrar(config, serviceRegistrarName, infrastructure);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/WeirdTypedLoadBalancerProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import static org.mockito.Mockito.mock;
4 |
5 | import io.smallrye.stork.api.LoadBalancer;
6 | import io.smallrye.stork.api.ServiceDiscovery;
7 | import io.smallrye.stork.api.config.LoadBalancerType;
8 | import io.smallrye.stork.spi.LoadBalancerProvider;
9 |
10 | @LoadBalancerType("these-arent-the-droids-youre-looking-for-selector")
11 | public class WeirdTypedLoadBalancerProvider
12 | implements LoadBalancerProvider {
13 | @Override
14 | public LoadBalancer createLoadBalancer(TheseArentTheDroidsYoureLookingForSelectorConfiguration config,
15 | ServiceDiscovery serviceDiscovery) {
16 | return mock(LoadBalancer.class);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/WeirdTypedServiceDiscoveryProvider.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import io.smallrye.mutiny.Uni;
4 | import io.smallrye.stork.api.ServiceDiscovery;
5 | import io.smallrye.stork.api.config.ServiceConfig;
6 | import io.smallrye.stork.api.config.ServiceDiscoveryType;
7 | import io.smallrye.stork.spi.ServiceDiscoveryProvider;
8 | import io.smallrye.stork.spi.StorkInfrastructure;
9 |
10 | @ServiceDiscoveryType("these-arent-the-droids-you-are-looking-for")
11 | public class WeirdTypedServiceDiscoveryProvider
12 | implements ServiceDiscoveryProvider {
13 | @Override
14 | public ServiceDiscovery createServiceDiscovery(TheseArentTheDroidsYouAreLookingForConfiguration config, String serviceName,
15 | ServiceConfig serviceConfig, StorkInfrastructure storkInfrastructure) {
16 | return () -> Uni.createFrom().item(() -> AnchoredServiceDiscoveryProvider.services);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/WeldTestBase.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork;
2 |
3 | import org.jboss.weld.environment.se.Weld;
4 | import org.jboss.weld.environment.se.WeldContainer;
5 |
6 | public class WeldTestBase {
7 |
8 | protected Weld weld;
9 | protected WeldContainer container;
10 |
11 | public WeldTestBase() {
12 | weld = new Weld();
13 | weld.addBeanClass(MyDataBean.class);
14 | TestEnv.configurations.clear();
15 | }
16 |
17 | public void run() {
18 | container = weld.initialize();
19 | }
20 |
21 | public void close() {
22 | if (container != null) {
23 | container.close();
24 | } else {
25 | weld.shutdown();
26 | }
27 | TestEnv.configurations.clear();
28 | }
29 |
30 | public T get(Class clazz) {
31 | return container.select(clazz).get();
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/core/src/test/java/io/smallrye/stork/utils/DurationUtilsTest.java:
--------------------------------------------------------------------------------
1 | package io.smallrye.stork.utils;
2 |
3 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
4 | import static org.junit.jupiter.api.Assertions.assertEquals;
5 |
6 | import java.time.Duration;
7 |
8 | import org.junit.jupiter.api.Test;
9 |
10 | public class DurationUtilsTest {
11 |
12 | @Test
13 | public void testOnlyNumberValueProvided() {
14 | Duration expectedDuration = Duration.ofSeconds(3);
15 | Duration actualDuration = DurationUtils.parseDuration("3", "refresh-period");
16 | assertEquals(expectedDuration, actualDuration);
17 | }
18 |
19 | @Test
20 | public void testNumberWithUnitValueProvided() {
21 | Duration expectedDuration = Duration.ofMinutes(3);
22 | Duration actualDuration = DurationUtils.parseDuration("3M", "refresh-period");
23 | assertEquals(expectedDuration, actualDuration);
24 | }
25 |
26 | @Test
27 | public void testValueStartingWithNumberAndInCorrectFormatProvided() {
28 | assertThatExceptionOfType(IllegalArgumentException.class)
29 | .isThrownBy(() -> {
30 | DurationUtils.parseDuration("-5", "refresh-period");
31 | }).withMessage("Negative refresh-period specified for service discovery: -5");
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/dco.txt:
--------------------------------------------------------------------------------
1 | Developer Certificate of Origin
2 | Version 1.1
3 |
4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
5 | 1 Letterman Drive
6 | Suite D4700
7 | San Francisco, CA, 94129
8 |
9 | Everyone is permitted to copy and distribute verbatim copies of this
10 | license document, but changing it is not allowed.
11 |
12 |
13 | Developer's Certificate of Origin 1.1
14 |
15 | By making a contribution to this project, I certify that:
16 |
17 | (a) The contribution was created in whole or in part by me and I
18 | have the right to submit it under the open source license
19 | indicated in the file; or
20 |
21 | (b) The contribution is based upon previous work that, to the best
22 | of my knowledge, is covered under an appropriate open source
23 | license and I have the right under that license to submit that
24 | work with modifications, whether created in whole or in part
25 | by me, under the same open source license (unless I am
26 | permitted to submit under a different license), as indicated
27 | in the file; or
28 |
29 | (c) The contribution was provided directly to me by some other
30 | person who certified (a), (b) or (c) and I have not modified
31 | it.
32 |
33 | (d) I understand and agree that this project and the contribution
34 | are public and that a record of the contribution (including all
35 | personal information I submit with it, including my sign-off) is
36 | maintained indefinitely and may be redistributed consistent with
37 | this project or the open source license(s) involved.
38 |
--------------------------------------------------------------------------------
/docs/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | url = "https://pypi.org/simple"
3 | verify_ssl = true
4 | name = "pypi"
5 |
6 | [packages]
7 | mkdocs = "*"
8 | mkdocs-material = "*"
9 | mkdocs-macros-plugin = "*"
10 | mkdocs-build-plantuml-plugin = "*"
11 | mike = "*"
12 |
13 | [dev-packages]
14 |
15 | [requires]
16 | python_version = "3.12"
17 |
--------------------------------------------------------------------------------
/docs/docs/diagrams/includes/themes/dark.puml:
--------------------------------------------------------------------------------
1 | !define BG_MAIN_COLOR #1A618C
2 | !define BG_SECONDARY_COLOR #616768
3 | !define BG_PACKAGE_COLOR #7a209f
4 | !define BORDER_COLOR #EEEEEE
5 | !define FONT_COLOR #EEEEEE
6 | !define ARROW_COLOR #EEEEEE
7 |
8 | ' include the general skinparams for both, light and dark
9 | ' to overwrite with the given settings
10 | !include general.puml
--------------------------------------------------------------------------------
/docs/docs/diagrams/includes/themes/light.puml:
--------------------------------------------------------------------------------
1 | !define BG_MAIN_COLOR AliceBlue
2 | !define BG_SECONDARY_COLOR #B4BCBE
3 | !define BG_PACKAGE_COLOR #eeb291
4 | !define BORDER_COLOR #444444
5 | !define FONT_COLOR #444444
6 | !define ARROW_COLOR DarkGrey
7 |
8 |
9 | ' include the general skinparams for both, light and dark
10 | ' to overwrite with the given settings
11 | !include general.puml
--------------------------------------------------------------------------------
/docs/docs/diagrams/observability_sequence.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 |
3 | !include diagrams/includes/themes/light.puml
4 |
5 | skinparam sequenceMessageAlign center
6 | autonumber "(0)"
7 |
8 |
9 | participant Application
10 | participant ObservableStorkInfrastructure
11 | participant ObservationCollector
12 | participant Stork
13 | participant Service
14 |
15 | Application -> ObservableStorkInfrastructure : instantiates
16 | ObservableStorkInfrastructure -> ObservationCollector : instantiates
17 | ObservationCollector -> ObservableStorkInfrastructure: ObservationCollector
18 | ObservableStorkInfrastructure -> Application: ObservableStorkInfrastructure
19 |
20 | ... ...
21 |
22 | Application -> Stork : initialize(observableInfrastructure)
23 | Stork -> Service : instantiates (..., ObservationCollector, ...)
24 | @enduml
--------------------------------------------------------------------------------
/docs/docs/diagrams/observation_sequence.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 |
3 | !include diagrams/includes/themes/light.puml
4 |
5 | skinparam sequenceMessageAlign center
6 | autonumber "(0)"
7 |
8 |
9 | participant Service
10 | participant ObservationCollector
11 | participant StorkObservation
12 | participant StorkEventHandler
13 |
14 | Service -> ObservationCollector : create("serviceName", sd type, ss type)
15 | ObservationCollector -> StorkObservation : instantiates
16 | StorkObservation -> StorkObservation: Registers start time
17 | ObservationCollector -> Service : StorkObservation
18 |
19 | ... ...
20 |
21 | Service -> StorkObservation : onServiceDiscoverySuccess(List)
22 | StorkObservation -> StorkObservation : Registers end service\ndiscovery time.\nRegisters instances count\n
23 | ... ...
24 |
25 | Service -> StorkObservation : onServiceDiscoveryFailure(Throwable)
26 | StorkObservation -> StorkObservation : Registers end service\ndiscovery time.\nRegisters failure cause\n
27 | ... ...
28 |
29 | Service -> StorkObservation : onServiceSelectionSuccess(instanceId)
30 | StorkObservation -> StorkObservation : Registers end service\nselection time.\nRegisters instance id\nRegisters overall duration\n
31 | StorkObservation -> StorkEventHandler: complete(this)
32 | ... ...
33 |
34 | Service -> StorkObservation : onServiceSelectionFailure(Throwable))
35 | StorkObservation -> StorkObservation : Registers overall duration.\nRegisters failure cause\n
36 | StorkObservation -> StorkEventHandler: complete(this)
37 | @enduml
--------------------------------------------------------------------------------
/docs/docs/diagrams/sequence.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 |
3 | !include diagrams/includes/themes/light.puml
4 |
5 | skinparam sequenceMessageAlign center
6 | autonumber "(0)"
7 |
8 |
9 | participant Application
10 | participant Stork
11 | participant ConfigProvider
12 | participant Service
13 | participant "Service Discovery"
14 | participant "Load Balancer"
15 |
16 | Application -> Stork : initialize()
17 | Stork -> ConfigProvider : getConfig()
18 | ConfigProvider -> Stork : : List
19 |
20 | ... ...
21 |
22 | Application -> Stork : getService("name")
23 | Stork -> Application: Service
24 |
25 | ... ...
26 |
27 |
28 | Application -> Service : selectServiceInstance()
29 | Service -> "Service Discovery" : getServiceInstances()
30 | "Service Discovery" ---> Service : Uni>
31 | Service -> "Load Balancer" : selectServiceInstance()
32 | "Load Balancer" ---> Service : Uni
33 | Service ---> Application : Uni
34 |
35 | @enduml
--------------------------------------------------------------------------------
/docs/docs/diagrams/srv_sequence.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 | !include diagrams/includes/themes/light.puml
3 |
4 | skinparam sequenceMessageAlign center
5 |
6 |
7 | participant Application
8 | participant Stork
9 | participant "DNS Server"
10 |
11 | Application -> Stork : get service instances
12 | Stork -> "DNS Server" : get SRV records for hostname
13 | "DNS Server" -> Stork : list of SRV records
14 | Stork -> Application : list of SRV record targets if no resolution desired
15 | Stork -> "DNS Server" : get A/AAAA records for each SRV record target
16 | "DNS Server" -> Stork : list of A/AAAA
17 | Stork -> Application : list of ServiceInstances
18 |
19 | @enduml
20 |
--------------------------------------------------------------------------------
/docs/docs/diagrams/stork.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 | !include diagrams/includes/themes/light.puml
3 | hide members
4 | class Stork <>
5 | interface ServiceDiscovery
6 | interface ServiceInstance
7 | interface LoadBalancer
8 | class Service <>
9 |
10 | Stork -- "*" Service
11 | Service -- ServiceDiscovery
12 | Service -- LoadBalancer
13 |
14 | Service --[dotted] ServiceInstance: selectServiceInstance
15 |
16 | class Kubernetes implements ServiceDiscovery
17 | class Consul implements ServiceDiscovery
18 | class "Custom Service Discovery" implements ServiceDiscovery
19 |
20 | class RoundRobin<> implements LoadBalancer
21 | class LeastResponseTime implements LoadBalancer
22 | class "Custom Load Balancer" implements LoadBalancer
23 |
24 | @enduml
--------------------------------------------------------------------------------
/docs/docs/extra.css:
--------------------------------------------------------------------------------
1 | .md-header__title {
2 | margin-left: 0 !important;
3 | }
4 |
5 | img {
6 | margin-left: auto;
7 | margin-right: auto;
8 | max-width: 80% !important;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/docs/docs/images/problem-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallrye/smallrye-stork/47751840baa0ae2fadc5e010e186526b86cb2bc6/docs/docs/images/problem-dark.png
--------------------------------------------------------------------------------
/docs/docs/images/problem-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallrye/smallrye-stork/47751840baa0ae2fadc5e010e186526b86cb2bc6/docs/docs/images/problem-light.png
--------------------------------------------------------------------------------
/docs/docs/images/redhat_reversed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/docs/images/solution-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallrye/smallrye-stork/47751840baa0ae2fadc5e010e186526b86cb2bc6/docs/docs/images/solution-dark.png
--------------------------------------------------------------------------------
/docs/docs/images/solution-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallrye/smallrye-stork/47751840baa0ae2fadc5e010e186526b86cb2bc6/docs/docs/images/solution-light.png
--------------------------------------------------------------------------------
/docs/docs/images/stork-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallrye/smallrye-stork/47751840baa0ae2fadc5e010e186526b86cb2bc6/docs/docs/images/stork-white.png
--------------------------------------------------------------------------------
/docs/docs/load-balancer/least-requests.md:
--------------------------------------------------------------------------------
1 | # Least Requests Load Balancing
2 |
3 | The `least-requests` load balancing strategy monitors the number of inflight calls and selects the less-used instance.
4 |
5 | This strategy keeps track of the inflight calls made by the application and picks the service instance with the smallest number of inflight requests:
6 |
7 | 1. when the selection happens, the service instance with the smallest number of inflight requests is selected, and this number is incremented
8 | 2. when the operation completes, successfully or not, the number of inflight requests is decremented
9 |
10 | ## Dependency
11 |
12 | First, you need to add the `least-requests` load-balancer to your project:
13 |
14 | ```xml
15 |
16 | io.smallrye.stork
17 | stork-load-balancer-least-requests
18 | {{version.current}}
19 |
20 | ```
21 |
22 | ## Configuration
23 |
24 | For each service expected to use a least-response-time selection, configure the `load-balancer` to be `least-requests`:
25 |
26 | === "stork standalone"
27 | ```properties
28 | stork.my-service.load-balancer.type=least-requests
29 | ```
30 |
31 | === "stork in quarkus"
32 | ```properties
33 | quarkus.stork.my-service.load-balancer.type=least-requests
34 | ```
35 |
36 | Supported configuration properties are the following:
37 |
38 | --8<-- "target/attributes/META-INF/stork-docs/least-requests-lb-attributes.txt"
--------------------------------------------------------------------------------
/docs/docs/load-balancer/overview.md:
--------------------------------------------------------------------------------
1 | ### Load Balancer / Service Selection in SmallRye Stork
2 |
3 | Once services are registered and discovered, the next critical step is selecting which service instance will handle a given request.
4 | SmallRye Stork provides flexible load balancing strategies to efficiently distribute requests across multiple instances of a service.
5 | This ensures optimal resource usage, improved performance, and high availability.
6 |
7 | #### Key Features:
8 | - **Multiple Load Balancing Strategies**: SmallRye Stork supports several built-in strategies for selecting service instances.
9 | Check them out in the following dedicated sections.
10 | - **Customizable Strategies**: You can define custom service selection strategies based on your unique use case or performance requirements, ensuring that the load balancer can adapt to specific needs.
11 |
12 | #### How it Works:
13 | Once a service has been registered and discovered, the load balancer comes into play when a client makes a request to that service.
14 | Stork applies the configured load balancing strategy to select an instance from the available pool of discovered services.
15 |
16 | This feature ensures that your services remain responsive, scalable, and resilient, providing a smooth experience for both users and developers.
17 |
--------------------------------------------------------------------------------
/docs/docs/load-balancer/power-of-two-choices.md:
--------------------------------------------------------------------------------
1 | # Power Of Two Choices Load Balancing
2 |
3 | The `power-of-two-choices` load balancing selects two random service instances and then chooses the one with the least inflight requests.
4 | It avoids the overhead of `least-requests` and the worst case for `random` where it selects a busy destination.
5 |
6 | This strategy acts as follows:
7 |
8 | 1. when the selection happens, it picks two random instances from the list,
9 | 2. it returns the least loaded instance (based on the number of inflight requests),
10 | 3. when the operation completes, successfully or not, the number of inflight requests for the instance is decremented.
11 |
12 | Check [The Power of Two Random Choices](http://www.eecs.harvard.edu/~michaelm/NEWWORK/postscripts/twosurvey.pdf) paper to learn more about this pattern and the benefits.
13 |
14 | ## Dependency
15 |
16 | First, you need to add the random load-balancer to your project:
17 |
18 | ```xml
19 |
20 | io.smallrye.stork
21 | stork-load-balancer-power-of-two-choices
22 | {{version.current}}
23 |
24 | ```
25 |
26 | ## Configuration
27 |
28 | For each service expected to use a random service selection, configure the `load-balancer` to be `power-of-two-choices`:
29 |
30 |
31 | === "stork standalone"
32 | ```properties
33 | stork.my-service.load-balancer.type=power-of-two-choices
34 | ```
35 |
36 | === "stork in quarkus"
37 | ```properties
38 | quarkus.stork.my-service.load-balancer.type=power-of-two-choices
39 | ```
40 |
41 | Supported configuration properties are the following:
42 |
43 | --8<-- "target/attributes/META-INF/stork-docs/power-of-two-choices-lb-attributes.txt"
--------------------------------------------------------------------------------
/docs/docs/load-balancer/random.md:
--------------------------------------------------------------------------------
1 | # Random Load Balancing
2 |
3 | The `random` load balancing is a straightforward service instance selection solution that picks a random instance every time.
4 |
5 | ## Dependency
6 |
7 | First, you need to add the random load-balancer to your project:
8 |
9 | ```xml
10 |
11 | io.smallrye.stork
12 | stork-load-balancer-random
13 | {{version.current}}
14 |
15 | ```
16 |
17 | ## Configuration
18 |
19 | For each service expected to use a random service selection, configure the `load-balancer` to be `random`:
20 |
21 | === "stork standalone"
22 | ```properties
23 | stork.my-service.load-balancer.type=random
24 | ```
25 |
26 | === "stork in quarkus"
27 | ```properties
28 | quarkus.stork.my-service.load-balancer.type=random
29 | ```
30 |
31 | Supported attributes are the following:
32 |
33 | --8<-- "target/attributes/META-INF/stork-docs/random-lb-attributes.txt"
34 |
--------------------------------------------------------------------------------
/docs/docs/load-balancer/round-robin.md:
--------------------------------------------------------------------------------
1 | # Round-Robin Load Balancing
2 |
3 | The round-robin is a straightforward load-balancing solution that just iterates over the set of service instances.
4 | While being simple, this solution shares the load among the instances and may be sufficient in many cases.
5 |
6 | The round-robin strategy is the default load-balancing strategy.
7 | It is provided by Stork itself, and so does not require an additional dependency.
8 |
9 | ## Configuration
10 |
11 | There is no need to configure the load-balancing strategy to be `round-robin`.
12 | Stork automatically uses this strategy when none are configured.
13 |
14 | However, you can also configure it explicitly as follows:
15 |
16 | === "stork standalone"
17 | ```properties
18 | stork.my-service.load-balancer.type=round-robin
19 | ```
20 |
21 | === "stork in quarkus"
22 | ```properties
23 | quarkus.stork.my-service.load-balancer.type=round-robin
24 | ```
25 |
--------------------------------------------------------------------------------
/docs/docs/load-balancer/sticky.md:
--------------------------------------------------------------------------------
1 | # Sticky Load Balancing
2 |
3 | The sticky load balancer selects a single service instance and keeps using it until it fails.
4 | Then, it selects another one.
5 |
6 | It is possible to configure a backoff time to specify for how long a failing service instance should not be retried.
7 |
8 | Precisely, the load balancer works as follows:
9 |
10 | * if no service instance has been selected so far, select the first instance from the collection;
11 | * else if the previously selected service instance has not failed, and is still available, return it;
12 | * else return the first available service instance that has no recorded failure, if one exists;
13 | * else, find the available instance for which the time since the last failure is the longest, and
14 | * if the backoff time since the failure passed, return it;
15 | * or, throw an `NoAcceptableServiceInstanceFoundException` as no acceptable instances are available.
16 |
17 | ## Configuration
18 |
19 | To use the `sticky` load service selection strategy, set the load balancer type to `sticky`:
20 |
21 | === "stork standalone"
22 | ```properties
23 | stork.my-service.load-balancer.type=sticky
24 | ```
25 |
26 | === "stork in quarkus"
27 | ```properties
28 | quarkus.stork.my-service.load-balancer.type=sticky
29 | ```
30 |
31 |
32 | The following attributes are supported:
33 |
34 | --8<-- "target/attributes/META-INF/stork-docs/sticky-lb-attributes.txt"
--------------------------------------------------------------------------------
/docs/docs/microprofile-config.md:
--------------------------------------------------------------------------------
1 | # Stork MicroProfile Config
2 |
3 | Stork integrates with MicroProfile Configuration out of the box, enabling seamless access to configuration properties.
4 | This documentation explains how Stork can retrieve configuration details from the MicroProfile Config file present in the classpath.
5 | Quarkus uses this approach for reading configuration details from the MicroProfile Config file located within the classpath.
6 |
7 |
8 | ## Dependency setup
9 |
10 | To enable MicroProfile Config integration in Stork, you need to include the following dependency:
11 |
12 | ```xml
13 |
14 | io.smallrye.stork
15 | smallrye-stork-microprofile
16 | {{version.current}}
17 |
18 | ```
19 |
20 | ## Initializing Stork
21 |
22 | If your framework lacks a pre-configured Stork instance, you'll need to perform initialization:
23 |
24 | ```java linenums="1"
25 | {{ insert('examples/InitializationExample.java') }}
26 | ```
27 | Upon initialization, Stork scans for the `io.smallrye.stork.config.MicroProfileConfigProvider` SPI provider and CDI beans (from version 2.x onwards). It then builds a comprehensive list of managed services by parsing the properties configuration files.
28 |
29 |
--------------------------------------------------------------------------------
/docs/docs/programmatic-api.md:
--------------------------------------------------------------------------------
1 | # Stork Programmatic API
2 |
3 | Stork proposes a programmatic API that lets you register new service Definitions and do manual lookup and selection.
4 | When using the programmatic API of Stork, you can:
5 | Retrieve the singleton Stork instance. This instance is configured with the set of Services it manages.
6 | Register new service definition.
7 | Retrieve the Service you want to use. Each Service is associated with a name.
8 | Retrieve the ServiceInstance, which will provide the metadata to access the actual instance.
9 |
10 |
11 | ## Initializing Stork
12 |
13 | If your framework does not already provide a configured `Stork` instance, you need to do:
14 |
15 | ```java linenums="1"
16 | {{ insert('examples/InitializationExample.java') }}
17 | ```
18 |
19 | ## Adding service dynamically
20 |
21 | To register a new `ServiceDefinition`, use the `defineIfAbsent` method:
22 |
23 | ```java linenums="1"
24 | {{ insert('examples/DefinitionExample.java') }}
25 | ```
26 |
27 | The `ServiceDefinition` instances can be created from:
28 |
29 | - A service discovery configuration - these classes are provided by the service discovery implementations,
30 | - An optional load balancer configuration - these classes are provided by the load balancer implementations
31 |
32 | Attributes from the service discovery and load balancer can be configured from the `Configuration` classes.
33 |
34 | ## Looking for service instances
35 |
36 | To list the service instances for a given service, or to select an instance according to the load balancer strategy, use the following code:
37 |
38 | ```java linenums="1"
39 | {{ insert('examples/LookupExample.java') }}
40 | ```
41 |
42 | The lookup and selection methods are returning Uni as these processes are asynchronous.
43 |
44 | ## All in one example
45 |
46 | The following snippet provides an _all in one_ example of the Stork programmatic API:
47 |
48 | ```java linenums="1"
49 | {{ insert('examples/StorkApiExample.java') }}
50 | ```
51 |
--------------------------------------------------------------------------------
/docs/docs/service-discovery/consul.md:
--------------------------------------------------------------------------------
1 | # Consul Service Discovery
2 |
3 | [Consul](https://www.consul.io/) is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure.
4 | It's often used as service discovery backend to register and locate the services composing your system.
5 | Consul makes it simple for services to register themselves and to discover other services via a DNS or HTTP interface.
6 | External services can be registered as well.
7 |
8 | As [specified](https://developer.hashicorp.com/consul/api-docs/agent/service#address) in the Consul documentation, if the host address is not provided, Stork will automatically use the Consul node address for the instance.
9 |
10 | This page explains how Stork can use Consul to handle the service discovery and service registration.
11 |
12 | ## Dependency
13 |
14 | First, you need to add the Stork Consul Service Discovery provider:
15 |
16 | ```xml
17 |
18 | io.smallrye.stork
19 | stork-service-discovery-consul
20 | {{version.current}}
21 |
22 | ```
23 |
24 | ### Service discovery configuration
25 |
26 | For each service that should get the service instances from Consul, configure the service discovery `type`:
27 |
28 | === "stork standalone"
29 | ```properties
30 | stork.my-service.service-discovery.type=consul
31 | ```
32 |
33 | === "stork in quarkus"
34 | ```properties
35 | quarkus.stork.my-service.service-discovery.type=consul
36 | ```
37 |
38 | Consul service discovery is configured with the following parameters:
39 |
40 | --8<-- "target/attributes/META-INF/stork-docs/consul-sd-attributes.txt"
41 |
42 |
--------------------------------------------------------------------------------
/docs/docs/service-discovery/eureka.md:
--------------------------------------------------------------------------------
1 | # Eureka Service Discovery
2 |
3 | [Eureka](https://github.com/Netflix/eureka) is a RESTful service that is primarily used in the AWS cloud for the purpose of discovery, load balancing, and failover of middle-tier servers.
4 |
5 | This page explains how Stork can use Eureka to handle the service discovery and service registration.
6 |
7 | ## Dependency
8 |
9 | First, you need to add the Stork Eureka Service Discovery provider:
10 |
11 | ```xml
12 |
13 | io.smallrye.stork
14 | stork-service-discovery-eureka
15 | {{version.current}}
16 |
17 | ```
18 |
19 | ### Service discovery configuration
20 |
21 | For each application instance expected to be registered in Eureka, configure the lookup:
22 |
23 | === "stork standalone"
24 | ```properties
25 | stork.my-service.service-discovery.type=eureka
26 | stork.my-service.service-discovery.eureka-host=localhost
27 | stork.my-service.service-discovery.eureka-port=8761
28 | ```
29 |
30 | === "stork in quarkus"
31 | ```properties
32 | quarkus.stork.my-service.service-discovery.type=eureka
33 | quarkus.stork.my-service.service-discovery.eureka-host=localhost
34 | quarkus.stork.my-service.service-discovery.eureka-port=8761
35 | ```
36 |
37 |
38 | Stork looks for the service with the given name (`my-service` in the previous example).
39 |
40 | Supported attributes are the following:
41 |
42 | --8<-- "target/attributes/META-INF/stork-docs/eureka-sd-attributes.txt"
43 |
44 | The `application` attribute is optional.
45 | It uses the Stork service name (`my-service` in the previous configuration) if not set.
46 |
47 | The `instance` attribute allows selecting a specific instance.
48 | Using this attribute prevents load-balancing as you will always select a single instance.
49 |
50 | The `secure` attribute indicates if you want the _secure virtual address_ of the application instance.
51 | If set to `true`, unsecured instances are filtered out from the available instances.
52 |
53 |
--------------------------------------------------------------------------------
/docs/docs/service-discovery/overview.md:
--------------------------------------------------------------------------------
1 | ### Service Discovery in SmallRye Stork
2 |
3 | As already introduced, service discovery is a crucial part of modern microservices architectures.
4 | It allows services to dynamically discover the location of other services at runtime, which is particularly useful in distributed systems where services may scale up or down,
5 | or change their network addresses.
6 |
7 | SmallRye Stork provides a flexible and extensible mechanism for service discovery.
8 | It supports out of the box some service discovery such as Kubernetes or Consul but the main strength of it is customization so you can easily create your own implementation related on your business for example.
9 | Stork allows services to communicate with each other without requiring hardcoded addresses, making it an ideal solution for microservices deployments.
10 | SmallRye Stork brings this capability to clients for Quarkus applications but it's vendor agnostic so you easily use it with other solutions and even in standalone mode.
11 |
12 | You can explore the different implementations and learn how to create your own in the following sections.
--------------------------------------------------------------------------------
/docs/docs/service-discovery/static-list.md:
--------------------------------------------------------------------------------
1 | # Static List Service Discovery
2 |
3 | In some situations, such as demos, development, or testing, you may want to mock the service discovery by providing a predefined list of service instances.
4 | For this purpose, Stork comes with a `static` service discovery type.
5 |
6 | ## Dependency
7 |
8 | To use the `static` service discovery, first add the appropriate Service Discovery provider dependency to your project:
9 |
10 | ```xml
11 |
12 | io.smallrye.stork
13 | stork-service-discovery-static-list
14 | {{version.current}}
15 |
16 | ```
17 |
18 | ## Configuration
19 |
20 | For each service that should use the static list of service instances configure the service registrar `type`:
21 |
22 | === "stork standalone"
23 | ```properties
24 | stork.my-service.service-discovery.type=static
25 | stork.my-service.service-discovery.address-list=localhost:8080,localhost:8081
26 | ```
27 |
28 | === "stork in quarkus"
29 | ```properties
30 | quarkus.stork.my-service.service-discovery.type=static
31 | quarkus.stork.my-service.service-discovery.address-list=localhost:8080,localhost:8081
32 | ```
33 |
34 | These are all the static service discovery parameters:
35 |
36 | --8<-- "target/attributes/META-INF/stork-docs/static-sd-attributes.txt"
37 |
--------------------------------------------------------------------------------
/docs/docs/service-registration/consul.md:
--------------------------------------------------------------------------------
1 | # Consul Service Registration
2 |
3 | [Consul](https://www.consul.io/) is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure.
4 | It's often used as service discovery backend to register and locate the services composing your system.
5 | Consul makes it simple for services to register themselves and to discover other services via a DNS or HTTP interface.
6 | External services can be registered as well.
7 |
8 | This page explains how Stork can use Consul to handle the service registration.
9 |
10 | ## Dependency
11 |
12 | First, you need to add the Stork Consul Service Registration provider:
13 |
14 | ```xml
15 |
16 | io.smallrye.stork
17 | stork-service-registration-consul
18 | {{version.current}}
19 |
20 | ```
21 |
22 | ## Service registration configuration
23 |
24 | For each service that should register the service instances in Consul, configure the service registrar `type`:
25 |
26 | === "stork standalone"
27 | ```properties
28 | stork.my-service.service-registrar.type=consul
29 | ```
30 |
31 | === "stork in quarkus"
32 | ```properties
33 | quarkus.stork.my-service.service-registrar.type=consul
34 | ```
35 |
36 | Consul service registrar is configured with the following parameters:
37 |
38 | --8<-- "target/attributes/META-INF/stork-docs/consul-sr-attributes.txt"
--------------------------------------------------------------------------------
/docs/docs/service-registration/eureka.md:
--------------------------------------------------------------------------------
1 | # Eureka Service Discovery
2 |
3 | [Eureka](https://github.com/Netflix/eureka) is a RESTful service that is primarily used in the AWS cloud for the purpose of discovery, load balancing, and failover of middle-tier servers.
4 |
5 | This page explains how Stork can use Eureka to handle the service registration.
6 |
7 | ## Dependency
8 |
9 | First, you need to add the Stork Eureka Service Registration provider:
10 |
11 | ```xml
12 |
13 | io.smallrye.stork
14 | stork-service-registration-eureka
15 | {{version.current}}
16 |
17 | ```
18 |
19 | ## Service registration configuration
20 |
21 | For each service that should register the service instances in Eureka, configure the service registrar `type`:
22 |
23 | === "stork standalone"
24 | ```properties
25 | stork.my-service.service-registrar.type=eureka
26 | stork.my-service.service-registrar.eureka-host=localhost
27 | stork.my-service.service-registrar.eureka-port=8761
28 | ```
29 |
30 | === "stork in quarkus"
31 | ```properties
32 | quarkus.stork.my-service.service-registrar.type=eureka
33 | quarkus.stork.my-service.service-registrar.eureka-host=localhost
34 | quarkus.stork.my-service.service-registrar.eureka-port=8761
35 | ```
36 |
37 | Eureka service registrar is configured with the following parameters:
38 |
39 | --8<-- "target/attributes/META-INF/stork-docs/eureka-sr-attributes.txt"
40 |
--------------------------------------------------------------------------------
/docs/docs/service-registration/overview.md:
--------------------------------------------------------------------------------
1 | ### Service Registration in SmallRye Stork
2 |
3 | Service registration is the process by which services announce their availability to a central registry, allowing other services to discover and communicate with them.
4 | In SmallRye Stork, service registration is automated and integrated with supported registries like **Consul**.
5 | This ensures that services can dynamically join and leave the network.
6 |
7 | #### Key Features:
8 | - **Automatic Registration**: For Quarkus applications, SmallRye Stork automatically registers it with the configured service registry (e.g., Consul).
9 |
10 | **IMPORTANT** Public IP address needs to be provided. Smallrye Stork will fail if the service IP address is not provided during registration.
11 |
12 | #### Supported Registries:
13 | Currently, Smallrye Stork provides seamless integration with **Consul**, Eureka and a Static registry.
14 | This integration simplifies the management of dynamic environments where services are frequently added or removed.
15 |
16 | #### Custom Registration:
17 | In addition to the default mechanisms, SmallRye Stork allows you to implement custom service registration strategies, providing flexibility for different infrastructures or custom service discovery needs.
18 |
19 | In the following sections you can have more details about each specific implementation.
--------------------------------------------------------------------------------
/docs/docs/service-registration/static-list.md:
--------------------------------------------------------------------------------
1 | # Static List Service Registration
2 |
3 | Stork provides the ability to register services using Static list as backend.
4 |
5 |
6 | ## Dependency
7 |
8 | To use the `static` service registrar, first add the appropriate Service Registration provider dependency to your project:
9 |
10 | ```xml
11 |
12 | io.smallrye.stork
13 | stork-service-registration-static-list
14 | {{version.current}}
15 |
16 | ```
17 |
18 | ## Service registration configuration
19 |
20 | For each service that should register the service instances in a static list, configure the service registrar `type`:
21 |
22 | === "stork standalone"
23 | ```properties
24 | stork.my-service.service-registrar.type=static
25 | ```
26 |
27 | === "stork in quarkus"
28 | ```properties
29 | quarkus.stork.my-service.service-registrar.type=static
30 | ```
31 |
32 | Static service registrar is configured with the following parameters:
33 |
34 | --8<-- "target/attributes/META-INF/stork-docs/static-sr-attributes.txt"
--------------------------------------------------------------------------------
/docs/docs/springboot-config.md:
--------------------------------------------------------------------------------
1 | # Stork Spring Boot Config
2 |
3 | Stork seamlessly supports Spring Boot configuration, facilitating access to configuration properties.
4 | This documentation elaborates on how Spring Boot developers can use Stork in their Spring Boot applications and configure it using the application.properties file.
5 |
6 |
7 | ## Dependency setup
8 |
9 | To enable Spring Boot configuration integration in Stork, you need to include the following dependency:
10 |
11 | ```xml
12 |
13 | io.smallrye.stork
14 | stork-spring-boot-config
15 | {{version.current}}
16 |
17 | ```
18 |
19 | ## Initializing Stork
20 |
21 | Since Spring Boot lacks a pre-configured Stork instance, you'll need create one. It can be done by providing a Spring bean performing Stork initialization:
22 |
23 | ```java linenums="1"
24 | {{ insert('examples/SpringBootInitializationExample.java') }}
25 | ```
26 | Upon initialization, Stork scans for the `io.smallrye.stork.springboot.SpringBootConfigProvider` SPI provider and CDI beans (from version 2.x onwards).
27 | It then builds a comprehensive list of managed services by parsing the properties configuration files.
28 |
29 |
30 | Please note the importance of the `io.smallrye.stork.springboot.SpringBootApplicationContextProvider` bean in our setup.
31 | This bean has a critical role by granting Stork access to the current `org.springframework.context.ApplicationContext`.
32 | It enables it to retrieve configuration details effectively. Consequently, it's imperative that this bean is instantiated prior to initiating the Stork initialization process.
33 | In this case, we utilize the `@DependsOn` annotation for that.
34 | It allows us controlling the bean creation order.
35 |
36 | ## Comprehensive Example
37 |
38 | You can check our [Guitar Hero Application](https://github.com/aureamunoz/spring-stork-guitar-hero/) showcasing the seamless integration of Stork with Spring Boot Configuration.
39 |
--------------------------------------------------------------------------------
/docs/mkdocs-customizations/macros/__pycache__/docissimo.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallrye/smallrye-stork/47751840baa0ae2fadc5e010e186526b86cb2bc6/docs/mkdocs-customizations/macros/__pycache__/docissimo.cpython-310.pyc
--------------------------------------------------------------------------------
/docs/mkdocs-customizations/overrides/main.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block outdated %}
4 | You are not viewing the latest version.
5 |
6 | Click here to go to latest.
7 |
8 | {% endblock %}
9 |
--------------------------------------------------------------------------------
/docs/mkdocs-customizations/overrides/partials/copyright.html:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |