Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CTECH-2979: Add retryingApiClient #106

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions sdk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,11 @@
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>${okhttp-mockwebserver-version}</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
Expand All @@ -395,6 +400,7 @@
<maven-plugin-version>1.0.0</maven-plugin-version>
<fasterxml-version>2.11.1</fasterxml-version>
<okhttp-version>4.9.1</okhttp-version>
<okhttp-mockwebserver-version>4.11.0</okhttp-mockwebserver-version>
<okio-version>2.10.0</okio-version>
<gson-version>2.8.5</gson-version>
<gson-fire-version>1.8.3</gson-fire-version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import com.finbourne.lusid.ApiClient;
import com.finbourne.lusid.utilities.auth.HttpLusidTokenProvider;
import com.finbourne.lusid.utilities.auth.RefreshingTokenProvider;
import com.finbourne.lusid.utilities.auth.LusidToken;
import com.finbourne.lusid.utilities.auth.LusidTokenException;
import com.finbourne.lusid.utilities.auth.RefreshingTokenProvider;
import okhttp3.OkHttpClient;

/**
Expand All @@ -15,73 +15,88 @@ public class ApiClientBuilder {
private static final int DEFAULT_TIMEOUT_SECONDS = 10;

/**
* Builds an ApiClient implementation configured against a secrets file. Typically used
* for communicating with LUSID via the APIs (e.g. {@link com.finbourne.lusid.api.TransactionPortfoliosApi}, {@link com.finbourne.lusid.api.QuotesApi}.
* Builds an ApiClient implementation configured against a secrets file.
* Typically used
* for communicating with LUSID via the APIs (e.g.
* {@link com.finbourne.lusid.api.TransactionPortfoliosApi},
* {@link com.finbourne.lusid.api.QuotesApi}.
*
* ApiClient implementation enables use of REFRESH tokens (see https://support.finbourne.com/using-a-refresh-token)
* ApiClient implementation enables use of REFRESH tokens (see
* https://support.finbourne.com/using-a-refresh-token)
* and automatically handles token refreshing on expiry.
*
* @param apiConfiguration configuration to connect to LUSID API
* @return
*
* @throws LusidTokenException on failing to authenticate and retrieve an initial {@link LusidToken}
* @throws LusidTokenException on failing to authenticate and retrieve an
* initial {@link LusidToken}
*/
public ApiClient build(ApiConfiguration apiConfiguration) throws LusidTokenException {

return this.build(apiConfiguration, DEFAULT_TIMEOUT_SECONDS, DEFAULT_TIMEOUT_SECONDS, DEFAULT_TIMEOUT_SECONDS);
return this.build(apiConfiguration, DEFAULT_TIMEOUT_SECONDS, DEFAULT_TIMEOUT_SECONDS, DEFAULT_TIMEOUT_SECONDS,
3);
}

/**
* Builds an ApiClient implementation configured against a secrets file. Typically used
* Builds an ApiClient implementation configured against a secrets file.
* Typically used
* for communicating with LUSID via the APIs
*
* ApiClient implementation enables use of REFRESH tokens (see https://support.finbourne.com/using-a-refresh-token)
* ApiClient implementation enables use of REFRESH tokens (see
* https://support.finbourne.com/using-a-refresh-token)
* and automatically handles token refreshing on expiry.
*
* @param apiConfiguration configuration to connect to {{application_camel}} API
* @param readTimeout read timeout in seconds
* @param writeTimeout write timeout in seconds
* @param readTimeout read timeout in seconds
* @param writeTimeout write timeout in seconds
* @return
*
* @throws LusidTokenException on failing to authenticate and retrieve an initial {@link LusidTokenException}
* @throws LusidTokenException on failing to authenticate and retrieve an
* initial {@link LusidTokenException}
*/
public ApiClient build(ApiConfiguration apiConfiguration, int readTimeout, int writeTimeout) throws LusidTokenException {
return this.build(apiConfiguration, readTimeout, writeTimeout, DEFAULT_TIMEOUT_SECONDS);
public ApiClient build(ApiConfiguration apiConfiguration, int readTimeout, int writeTimeout)
throws LusidTokenException {
return build(apiConfiguration, readTimeout, writeTimeout, DEFAULT_TIMEOUT_SECONDS, 3);
}

/**
* Builds an ApiClient implementation configured against a secrets file. Typically used
* Builds an ApiClient implementation configured against a secrets file.
* Typically used
* for communicating with LUSID via the APIs
*
* ApiClient implementation enables use of REFRESH tokens (see https://support.finbourne.com/using-a-refresh-token)
* ApiClient implementation enables use of REFRESH tokens (see
* https://support.finbourne.com/using-a-refresh-token)
* and automatically handles token refreshing on expiry.
*
* @param apiConfiguration configuration to connect to {{application_camel}} API
* @param readTimeout read timeout in seconds
* @param writeTimeout write timeout in seconds
* @param connectTimeout connection timeout in seconds
* @param readTimeout read timeout in seconds
* @param writeTimeout write timeout in seconds
* @param connectTimeout connection timeout in seconds
* @return
*
* @throws LusidTokenException on failing to authenticate and retrieve an initial {@link LusidTokenException}
* @throws LusidTokenException on failing to authenticate and retrieve an
* initial {@link LusidTokenException}
*/
public ApiClient build(ApiConfiguration apiConfiguration, int readTimeout, int writeTimeout, int connectTimeout) throws LusidTokenException {

public ApiClient build(ApiConfiguration apiConfiguration, int readTimeout, int writeTimeout, int connectTimeout,
int retryMaxAttempts)
throws LusidTokenException {
// http client to use for api and auth calls
OkHttpClient httpClient = createHttpClient(apiConfiguration, readTimeout, writeTimeout, connectTimeout);

if (apiConfiguration.getPersonalAccessToken() != null && apiConfiguration.getApiUrl() != null) {

// use Personal Access Token
// use Personal Access Token
LusidToken lusidToken = new LusidToken(apiConfiguration.getPersonalAccessToken(), null, null);
ApiClient defaultApiClient = createDefaultApiClient(apiConfiguration, httpClient, lusidToken);
ApiClient defaultApiClient = createDefaultApiClient(apiConfiguration, httpClient, lusidToken,
retryMaxAttempts);

return defaultApiClient;

}
else {
} else {

// token provider to keep client authenticated with automated token refreshing
RefreshingTokenProvider refreshingTokenProvider = new RefreshingTokenProvider(new HttpLusidTokenProvider(apiConfiguration, httpClient));
RefreshingTokenProvider refreshingTokenProvider = new RefreshingTokenProvider(
new HttpLusidTokenProvider(apiConfiguration, httpClient));
LusidToken lusidToken = refreshingTokenProvider.get();

// setup api client that managed submissions with the latest token
Expand All @@ -90,8 +105,14 @@ public ApiClient build(ApiConfiguration apiConfiguration, int readTimeout, int w
}
}

ApiClient createDefaultApiClient(ApiConfiguration apiConfiguration, OkHttpClient httpClient, LusidToken lusidToken) throws LusidTokenException {
ApiClient apiClient = createApiClient();
ApiClient createDefaultApiClient(ApiConfiguration apiConfiguration, OkHttpClient httpClient,
LusidToken lusidToken) throws LusidTokenException {
return createDefaultApiClient(apiConfiguration, httpClient, lusidToken, 3);
}

ApiClient createDefaultApiClient(ApiConfiguration apiConfiguration, OkHttpClient httpClient,
LusidToken lusidToken, int retryMaxAttempts) throws LusidTokenException {
ApiClient apiClient = createApiClient(retryMaxAttempts);

apiClient.setHttpClient(httpClient);

Expand All @@ -107,15 +128,20 @@ ApiClient createDefaultApiClient(ApiConfiguration apiConfiguration, OkHttpClient
}
apiClient.setBasePath(apiConfiguration.getApiUrl());

return apiClient;
return apiClient;
}

private OkHttpClient createHttpClient(ApiConfiguration apiConfiguration, int readTimeout, int writeTimeout, int connectTimeout){
private OkHttpClient createHttpClient(ApiConfiguration apiConfiguration, int readTimeout, int writeTimeout,
int connectTimeout) {
return new HttpClientFactory().build(apiConfiguration, readTimeout, writeTimeout, connectTimeout);
}

// allows us to mock out api client for testing purposes
ApiClient createApiClient(){
return new ApiClient();
ApiClient createApiClient() {
return new RetryingApiClient(3);
}

ApiClient createApiClient(int maxAttempts) {
return new RetryingApiClient(maxAttempts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,57 @@ public class LusidApiFactoryBuilder {
private static final int DEFAULT_TIMEOUT_SECONDS = 10;

/**
* Build a {@link LusidApiFactory} defining configuration using environment variables. For details on the environment arguments see https://support.lusid.com/getting-started-with-apis-sdks.
* Build a {@link LusidApiFactory} defining configuration using environment
* variables. For details on the environment arguments see
* https://support.lusid.com/getting-started-with-apis-sdks.
*
* @return
*/
public static LusidApiFactory build() throws ApiConfigurationException, LusidTokenException {
if (!areRequiredEnvironmentVariablesSet()) {
throw new ApiConfigurationException("Environment variables to configure LUSID API client have not been set. See " +
" see https://support.lusid.com/getting-started-with-apis-sdks for details.");
throw new ApiConfigurationException(
"Environment variables to configure LUSID API client have not been set. See " +
" see https://support.lusid.com/getting-started-with-apis-sdks for details.");
}
return createApiFactory(null, DEFAULT_TIMEOUT_SECONDS, DEFAULT_TIMEOUT_SECONDS, DEFAULT_TIMEOUT_SECONDS);
}

/**
* Build a {@link LusidApiFactory} using the specified configuration file. For details on the format of the configuration file see https://support.lusid.com/getting-started-with-apis-sdks.
* Build a {@link LusidApiFactory} using the specified configuration file. For
* details on the format of the configuration file see
* https://support.lusid.com/getting-started-with-apis-sdks.
*/
public static LusidApiFactory build(String configurationFile) throws ApiConfigurationException, LusidTokenException {
public static LusidApiFactory build(String configurationFile)
throws ApiConfigurationException, LusidTokenException {
return build(configurationFile, 10, 10);
}

public static LusidApiFactory build(String configurationFile, int readTimeout, int writeTimeout) throws ApiConfigurationException, LusidTokenException {
public static LusidApiFactory build(String configurationFile, int readTimeout, int writeTimeout)
throws ApiConfigurationException, LusidTokenException {
return createApiFactory(configurationFile, readTimeout, writeTimeout, DEFAULT_TIMEOUT_SECONDS);
}

public static LusidApiFactory build(String configurationFile, int readTimeout, int writeTimeout, int connectTimeout) throws ApiConfigurationException, LusidTokenException {
public static LusidApiFactory build(String configurationFile, int readTimeout, int writeTimeout, int connectTimeout)
throws ApiConfigurationException, LusidTokenException {
return createApiFactory(configurationFile, readTimeout, writeTimeout, connectTimeout);
}

private static LusidApiFactory createApiFactory(String configurationFile, int readTimeout, int writeTimeout, int connectTimeout) throws ApiConfigurationException, LusidTokenException {
private static LusidApiFactory createApiFactory(String configurationFile, int readTimeout, int writeTimeout,
int connectTimeout) throws ApiConfigurationException, LusidTokenException {
ApiConfiguration apiConfiguration = new ApiConfigurationBuilder().build(configurationFile);
ApiClient apiClient = new ApiClientBuilder().build(apiConfiguration, readTimeout, writeTimeout, connectTimeout);
return new LusidApiFactory(apiClient);
ApiClient apiClient = new ApiClientBuilder().build(apiConfiguration, readTimeout, writeTimeout, connectTimeout,
3);
return new LusidApiFactory(apiClient);
}

private static boolean areRequiredEnvironmentVariablesSet(){
private static boolean areRequiredEnvironmentVariablesSet() {
return ((System.getenv("FBN_TOKEN_URL") != null &&
System.getenv("FBN_USERNAME") != null &&
System.getenv("FBN_PASSWORD") != null &&
System.getenv("FBN_CLIENT_ID") != null &&
System.getenv("FBN_CLIENT_SECRET") != null &&
System.getenv("FBN_LUSID_API_URL") != null) ||
(System.getenv("FBN_TOKEN_URL") != null &&
System.getenv("FBN_ACCESS_TOKEN") != null));
System.getenv("FBN_ACCESS_TOKEN") != null));
}
}
Loading