org.kiwiproject.registry.client.RegistryClient Maven / Gradle / Ivy
package org.kiwiproject.registry.client;
import static org.apache.commons.lang3.StringUtils.isBlank;
import lombok.Builder;
import lombok.Getter;
import org.kiwiproject.registry.model.ServiceInstance;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
/**
* Base of all registry client implementations in order to find running services
*/
public interface RegistryClient {
/**
* Encapsulates search parameters for finding service instances
*
* Note: serviceName is required
*/
@Builder
@Getter
class InstanceQuery {
private final String serviceName;
private final String minimumVersion;
private final String preferredVersion;
public boolean hasNoVersionPredicates() {
return hasNoMinimumVersion() && hasNoPreferredVersion();
}
public boolean hasNoMinimumVersion() {
return isBlank(minimumVersion);
}
public boolean hasNoPreferredVersion() {
return isBlank(preferredVersion);
}
}
/**
* Attempts to find a service instance with the given service name.
*
* If there are more than one instance, the implementation should decide the order in which the service is returned
* (e.g. round-robin, random, LIFO, FIFO, etc.)
*
* @param serviceName The name of the service that is being requested
* @return an {@link Optional} containing the found service or {@code Optional.empty()}
*/
default Optional findServiceInstanceBy(String serviceName) {
return findServiceInstanceBy(InstanceQuery.builder().serviceName(serviceName).build());
}
/**
* Attempts to find a service instance with the given service name and the given instance id.
*
* @param serviceName The name of the service that is being requested
* @param instanceId The id of the instance that is wanted
* @return an {@link Optional} containing the found service or {@code Optional.empty()}
*/
Optional findServiceInstanceBy(String serviceName, String instanceId);
/**
* Attempts to find a service instance from the given {@link InstanceQuery}.
*
* If there are more than one instance, the implementation should decide the order in which the service is returned
* (e.g. round-robin, random, LIFO, FIFO, etc.)
*
* @param query a {@link InstanceQuery} containing the search parameters to find the instance
* @return an {@link Optional} containing the found service or {@code Optional.empty()}
*/
default Optional findServiceInstanceBy(InstanceQuery query) {
var instances = findAllServiceInstancesBy(query);
if (instances.isEmpty()) {
return Optional.empty();
}
return Optional.of(selectRandom(instances));
}
/**
* Attempts to find all service instances with the given service name.
*
* @param serviceName The name of the service that is being requested
* @return a {@link List} containing the found services
*/
default List findAllServiceInstancesBy(String serviceName) {
return findAllServiceInstancesBy(InstanceQuery.builder().serviceName(serviceName).build());
}
/**
* Attempts to find all service instances from the given {@link InstanceQuery}.
*
* @param query a {@link InstanceQuery} containing the search parameters to find the instance
* @return a {@link List} containing the found services
*/
List findAllServiceInstancesBy(InstanceQuery query);
private static T selectRandom(List items) {
var index = selectRandomIndex(items);
return items.get(index);
}
private static int selectRandomIndex(List items) {
return ThreadLocalRandom.current().nextInt(items.size());
}
/**
* Retrieves all registered service instances from the registry.
*
* @return a {@link List} containing all registered service instances
*/
List retrieveAllRegisteredInstances();
}