com.hotels.road.offramp.client.OfframpOptions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of road-offramp-client Show documentation
Show all versions of road-offramp-client Show documentation
Data Highway consumer client
/**
* Copyright (C) 2016-2019 Expedia Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hotels.road.offramp.client;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.joining;
import static lombok.AccessLevel.PACKAGE;
import static com.hotels.road.offramp.model.DefaultOffset.LATEST;
import static com.hotels.road.rest.model.Sensitivity.PUBLIC;
import java.io.Serializable;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hotels.road.offramp.model.DefaultOffset;
import com.hotels.road.rest.model.Sensitivity;
import com.hotels.road.tls.TLSConfig;
@EqualsAndHashCode(exclude = {"payloadTypeFactory"})
@RequiredArgsConstructor(access = PACKAGE)
public class OfframpOptions implements Serializable {
private static final long serialVersionUID = 1L;
private final @Getter String username;
private final @Getter String password;
private final @NonNull String host;
private final @NonNull String roadName;
private final @NonNull String streamName;
private final @NonNull DefaultOffset defaultOffset;
private final @NonNull Set grants;
private final @NonNull Class payloadClass;
private final @NonNull PayloadTypeFactory payloadTypeFactory;
private final PayloadDeserializer payloadDeserialiser;
private final @Getter(PACKAGE) boolean retry;
private final @Getter(PACKAGE) int initialRequestAmount;
private final @Getter(PACKAGE) int replenishingRequestAmount;
private final @Getter(PACKAGE) long keepAliveSeconds;
private final @Getter(PACKAGE) TLSConfig.Factory tlsConfigFactory;
URI uri() {
String grantsParam = grants.stream().map(Sensitivity::name).collect(joining(","));
return URI.create(String.format("wss://%s/offramp/v2/roads/%s/streams/%s/messages?defaultOffset=%s&grants=%s", host,
roadName, streamName, defaultOffset.name(), grantsParam));
}
ObjectMapper objectMapper() {
return ObjectMapperFactory.create(payloadClass, payloadTypeFactory, payloadDeserialiser);
}
public static Builder builder(Class payloadClass) {
return new Builder(payloadClass);
}
@RequiredArgsConstructor(access = PACKAGE)
public static class Builder {
private String username;
private String password;
private String host;
private String roadName;
private String streamName;
private DefaultOffset defaultOffset = LATEST;
private Set grants = emptySet();
private final Class payloadClass;
private PayloadTypeFactory payloadTypeFactory;
private PayloadDeserializer payloadDeserialiser;
private boolean retry = true;
private int initialRequestAmount = 4000;
private int replenishingRequestAmount = 1000;
private long keepAliveSeconds = 30;
private TLSConfig.Factory tlsConfigFactory;
/**
* Required. The user name credential to authenticate with Data Highway.
*
* @param username The username.
* @return {@link Builder this}
*/
public Builder username(@NonNull String username) {
this.username = username;
return this;
}
/**
* Required. The password to authenticate with Data Highway.
*
* @param password The password.
* @return {@link Builder this}
*/
public Builder password(@NonNull String password) {
this.password = password;
return this;
}
/**
* Required. The Data Highway host.
*
* @param host The Data Highway host.
* @return {@link Builder this}
*/
public Builder host(@NonNull String host) {
this.host = host;
return this;
}
/**
* Required. The road name.
*
* @param roadName The road name.
* @return {@link Builder this}
*/
public Builder roadName(@NonNull String roadName) {
this.roadName = roadName;
return this;
}
/**
* Required. The stream name.
*
* @param streamName The stream name.
* @return {@link Builder this}
*/
public Builder streamName(@NonNull String streamName) {
this.streamName = streamName;
return this;
}
/**
* Optional. The {@link DefaultOffset} to start streaming at on each partition if no commit exists. Defaults to
* {@link DefaultOffset#LATEST LATEST} if not provided.
*
* @param defaultOffset The {@link DefaultOffset}.
* @return {@link Builder this}
*/
public Builder defaultOffset(@NonNull DefaultOffset defaultOffset) {
this.defaultOffset = defaultOffset;
return this;
}
/**
* Optional. Determines which data sensitivity types should be consumed unobfuscated. Public data is always served
* unobfuscated.
*
* @param grants The {@link Set} of {@link Sensitivity} grants.
* @return {@link Builder this}
*/
public Builder grants(@NonNull Set grants) {
if (grants.contains(PUBLIC)) {
throw new IllegalArgumentException("PUBLIC is not a required grant");
}
this.grants = new HashSet<>(grants);
return this;
}
/**
* Optional. Defaults to the equivalent of {@code tf -> tf.constructType(payloadClass)}. Will only be needed if the
* payload type itself is a generic type.
*
* @param payloadTypeFactory The {@link PayloadTypeFactory}.
* @return {@link Builder this}
*/
public Builder payloadTypeFactory(@NonNull PayloadTypeFactory payloadTypeFactory) {
this.payloadTypeFactory = payloadTypeFactory;
return this;
}
/**
* Optional. May be needed if any specific code is required for deserialisation to the payload type.
*
* @param payloadDeserialiser A custom {@link JsonDeserializer}.
* @return {@link Builder this}
*/
public Builder payloadDeserialiser(@NonNull PayloadDeserializer payloadDeserialiser) {
this.payloadDeserialiser = payloadDeserialiser;
return this;
}
/**
* Optional. Specifies whether the client should reacquire a connection to offramp and retry when errors occur.
* Default is true - infinite retries with a backoff of 1 second.
*
* @param retry Whether retries are enabled.
* @return {@link Builder this}
*/
public Builder retry(boolean retry) {
this.retry = retry;
return this;
}
/**
* Optional. Parameters for configuring poll mechanism.
*
* @param initialRequestAmount Defines how many messages will be requested on the first call to Offramp Server.
* @param replenishingRequestAmount Defines how many messages will be requested on subsequent requests. The
* subsequent requests will only happen after that many messages are consumed downstream.
* @return {@link Builder this}
*/
public Builder requestBuffer(int initialRequestAmount, int replenishingRequestAmount) {
this.initialRequestAmount = initialRequestAmount;
this.replenishingRequestAmount = replenishingRequestAmount;
return this;
}
/**
* Optional. Specifies how often keep-alive signals should be sent. A value of less than or equal to 0 will disable
* keep-alive signals. The default is 30. Enabling keep-alive signals would suit consumers of roads with sparse
* data, allowing them to stay connected during periods of no data.
*
* @param keepAliveSeconds The number
* @return {@link Builder this}
*/
public Builder keepAliveSeconds(long keepAliveSeconds) {
this.keepAliveSeconds = keepAliveSeconds;
return this;
}
/**
* Optional. Allows custom {@link SSLContext} and {@link HostnameVerifier} if alternative TLS behaviour is required.
*
* @param tlsConfigFactory The {@link TLSConfig.Factory}
* @return {@link Builder this}
*/
public Builder tlsConfigFactory(TLSConfig.Factory tlsConfigFactory) {
this.tlsConfigFactory = tlsConfigFactory;
return this;
}
/**
* Creates an {@link OfframpOptions} instance.
*
* @return {@link OfframpOptions}
*/
public OfframpOptions build() {
if ((username == null && password != null) || (username != null && password == null)) {
throw new IllegalStateException("Both username and password must be set or neither");
}
if (payloadTypeFactory == null) {
payloadTypeFactory = PayloadTypeFactory.fromClass(payloadClass);
}
return new OfframpOptions<>(username, password, host, roadName, streamName, defaultOffset, grants, payloadClass,
payloadTypeFactory, payloadDeserialiser, retry, initialRequestAmount, replenishingRequestAmount,
keepAliveSeconds, tlsConfigFactory);
}
}
}