From 3ca9a66323082c8a3354d85f0b9ccfec73885886 Mon Sep 17 00:00:00 2001 From: Ravi Khadiwala Date: Wed, 8 Jan 2025 14:48:44 -0600 Subject: [PATCH] Stripe HTTP2 clients in CloudflareTurnCredentialsManager --- service/config/sample.yml | 1 + .../textsecuregcm/WhisperServerService.java | 1 + .../CloudflareTurnCredentialsManager.java | 21 +++++++++++++++++-- .../CloudflareTurnConfiguration.java | 4 +++- .../CloudflareTurnCredentialsManagerTest.java | 1 + service/src/test/resources/config/test.yml | 1 + 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/service/config/sample.yml b/service/config/sample.yml index 5a3f1e762..7e4af1533 100644 --- a/service/config/sample.yml +++ b/service/config/sample.yml @@ -484,6 +484,7 @@ turn: - turns:%s:443?transport=tcp ttl: 86400 hostname: turn.cloudflare.example.com + numHttpClients: 1 linkDevice: secret: secret://linkDevice.secret diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 537f7222b..e57ee20d4 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -677,6 +677,7 @@ public class WhisperServerService extends Application cloudflareTurnUrls; private final List cloudflareTurnUrlsWithIps; private final String cloudflareTurnHostname; @@ -51,8 +57,9 @@ public class CloudflareTurnCredentialsManager { public CloudflareTurnCredentialsManager(final String cloudflareTurnApiToken, final String cloudflareTurnEndpoint, final long cloudflareTurnTtl, final List cloudflareTurnUrls, final List cloudflareTurnUrlsWithIps, final String cloudflareTurnHostname, - final CircuitBreakerConfiguration circuitBreaker, final ExecutorService executor, final RetryConfiguration retry, - final ScheduledExecutorService retryExecutor, final DnsNameResolver dnsNameResolver) { + final int cloudflareTurnNumHttpClients, final CircuitBreakerConfiguration circuitBreaker, + final ExecutorService executor, final RetryConfiguration retry, final ScheduledExecutorService retryExecutor, + final DnsNameResolver dnsNameResolver) { this.cloudflareTurnClient = FaultTolerantHttpClient.newBuilder() .withName("cloudflare-turn") @@ -60,6 +67,7 @@ public class CloudflareTurnCredentialsManager { .withExecutor(executor) .withRetry(retry) .withRetryExecutor(retryExecutor) + .withNumClients(cloudflareTurnNumHttpClients) .build(); this.cloudflareTurnUrls = cloudflareTurnUrls; this.cloudflareTurnUrlsWithIps = cloudflareTurnUrlsWithIps; @@ -93,11 +101,20 @@ public class CloudflareTurnCredentialsManager { throw new IOException(e); } + final Timer.Sample sample = Timer.start(); final HttpResponse response; try { response = cloudflareTurnClient.sendAsync(request, HttpResponse.BodyHandlers.ofString()).join(); + sample.stop(Timer.builder(CREDENTIAL_FETCH_TIMER_NAME) + .publishPercentileHistogram(true) + .tags("outcome", "success") + .register(Metrics.globalRegistry)); } catch (CompletionException e) { logger.warn("failed to make http request to Cloudflare Turn: {}", e.getMessage()); + sample.stop(Timer.builder(CREDENTIAL_FETCH_TIMER_NAME) + .publishPercentileHistogram(true) + .tags("outcome", "failure") + .register(Metrics.globalRegistry)); throw new IOException(ExceptionUtils.unwrap(e)); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/CloudflareTurnConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/CloudflareTurnConfiguration.java index c9decf9b4..52df5f84b 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/CloudflareTurnConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/CloudflareTurnConfiguration.java @@ -9,6 +9,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import java.util.List; +import jakarta.validation.constraints.Positive; import org.whispersystems.textsecuregcm.configuration.secrets.SecretString; public record CloudflareTurnConfiguration(@NotNull SecretString apiToken, @@ -18,7 +19,8 @@ public record CloudflareTurnConfiguration(@NotNull SecretString apiToken, @NotBlank List urlsWithIps, @NotNull @Valid CircuitBreakerConfiguration circuitBreaker, @NotNull @Valid RetryConfiguration retry, - @NotBlank String hostname) { + @NotBlank String hostname, + @Positive int numHttpClients) { public CloudflareTurnConfiguration { if (circuitBreaker == null) { diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/CloudflareTurnCredentialsManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/CloudflareTurnCredentialsManagerTest.java index 913522ff1..e5b814a72 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/CloudflareTurnCredentialsManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/CloudflareTurnCredentialsManagerTest.java @@ -61,6 +61,7 @@ public class CloudflareTurnCredentialsManagerTest { List.of("turn:cf.example.com"), List.of("turn:%s", "turn:%s:80?transport=tcp", "turns:%s:443?transport=tcp"), TURN_HOSTNAME, + 2, new CircuitBreakerConfiguration(), httpExecutor, new RetryConfiguration(), diff --git a/service/src/test/resources/config/test.yml b/service/src/test/resources/config/test.yml index 9590ff89e..74ea169c6 100644 --- a/service/src/test/resources/config/test.yml +++ b/service/src/test/resources/config/test.yml @@ -478,6 +478,7 @@ turn: - turn:%s:80?transport=tcp - turns:%s:443?transport=tcp hostname: turn.cloudflare.example.com + numHttpClients: 1 linkDevice: secret: secret://linkDevice.secret