Skip to content

Commit 8ffb825

Browse files
Merge pull request #1726 from stripe/richardm/merge-java-beta
Merge java beta
2 parents e8bd408 + 39432ab commit 8ffb825

File tree

143 files changed

+718
-82
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+718
-82
lines changed

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ tasks.withType(JavaCompile) {
5050
// com.stripe.param.AccountUpdateParams.Individual.Address] within this file.)
5151
// We should fix this by having autogen use the fully-qualified class to eliminate ambiguity.
5252
check("SameNameButDifferent", net.ltgt.gradle.errorprone.CheckSeverity.OFF)
53+
54+
// InlineMe (https://errorprone.info/docs/inlineme) seems neat, but in order to add these annotations
55+
// we would be imposing another dependency on `errorprone` to our users, not worth it.
56+
check("InlineMeSuggester", net.ltgt.gradle.errorprone.CheckSeverity.OFF)
5357
}
5458
}
5559

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,49 @@
11
package com.stripe.net;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
35
import java.util.Map;
46
import lombok.Getter;
57

68
@Getter
79
public class ApiRequest extends BaseApiRequest {
810
private Map<String, Object> params;
911

12+
private ApiRequest(
13+
BaseAddress baseAddress,
14+
ApiResource.RequestMethod method,
15+
String path,
16+
RequestOptions options,
17+
ApiMode apiMode,
18+
List<String> usage,
19+
Map<String, Object> params) {
20+
super(baseAddress, method, path, options, apiMode, usage);
21+
this.params = params;
22+
}
23+
1024
public ApiRequest(
1125
BaseAddress baseAddress,
1226
ApiResource.RequestMethod method,
1327
String path,
1428
Map<String, Object> params,
1529
RequestOptions options,
1630
ApiMode apiMode) {
17-
super(baseAddress, method, path, options, apiMode);
18-
this.params = params;
31+
this(baseAddress, method, path, options, apiMode, null, params);
32+
}
33+
34+
public ApiRequest addUsage(String usage) {
35+
List<String> newUsage = new ArrayList<>();
36+
if (this.getUsage() != null) {
37+
newUsage.addAll(this.getUsage());
38+
}
39+
newUsage.add(usage);
40+
return new ApiRequest(
41+
this.getBaseAddress(),
42+
this.getMethod(),
43+
this.getPath(),
44+
this.getOptions(),
45+
this.getApiMode(),
46+
newUsage,
47+
this.getParams());
1948
}
2049
}
Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
11
package com.stripe.net;
22

33
import java.util.List;
4+
import lombok.AccessLevel;
5+
import lombok.AllArgsConstructor;
46
import lombok.Getter;
5-
import lombok.Setter;
67

78
@Getter
9+
@AllArgsConstructor(access = AccessLevel.PROTECTED)
810
class BaseApiRequest {
9-
private BaseAddress baseAddress;
10-
private ApiResource.RequestMethod method;
11-
private String path;
12-
private RequestOptions options;
13-
private ApiMode apiMode;
11+
private final BaseAddress baseAddress;
12+
private final ApiResource.RequestMethod method;
13+
private final String path;
14+
private final RequestOptions options;
15+
private final ApiMode apiMode;
1416

15-
@Setter private List<String> usage;
17+
// TODO (major): Remove setter and make final
18+
private List<String> usage;
1619

17-
public BaseApiRequest(
18-
BaseAddress baseAddress,
19-
ApiResource.RequestMethod method,
20-
String path,
21-
RequestOptions options,
22-
ApiMode apiMode) {
23-
this.baseAddress = baseAddress;
24-
this.method = method;
25-
this.path = path;
26-
this.options = options;
27-
this.apiMode = apiMode;
20+
/** @deprecated Use {@link com.stripe.net.ApiRequest#addUsage(String)} instead. */
21+
@Deprecated
22+
public void setUsage(List<String> usage) {
23+
this.usage = usage;
2824
}
2925
}

src/main/java/com/stripe/net/HttpClient.java

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
import com.stripe.Stripe;
44
import com.stripe.exception.ApiConnectionException;
55
import com.stripe.exception.StripeException;
6-
import com.stripe.util.Stopwatch;
76
import java.net.ConnectException;
87
import java.net.SocketTimeoutException;
98
import java.time.Duration;
109
import java.util.HashMap;
1110
import java.util.Map;
12-
import java.util.Optional;
1311
import java.util.concurrent.ThreadLocalRandom;
1412

1513
/** Base abstract class for HTTP clients used to send requests to Stripe's API. */
@@ -20,8 +18,6 @@ public abstract class HttpClient {
2018
/** Minimum sleep time between tries to send HTTP requests after network failure. */
2119
public static final Duration minNetworkRetriesDelay = Duration.ofMillis(500);
2220

23-
private final RequestTelemetry requestTelemetry = new RequestTelemetry();
24-
2521
/** A value indicating whether the client should sleep between automatic request retries. */
2622
boolean networkRetriesSleep = true;
2723

@@ -52,48 +48,27 @@ public StripeResponseStream requestStream(StripeRequest request) throws StripeEx
5248
private interface RequestSendFunction<R> {
5349
R apply(StripeRequest request) throws StripeException;
5450
}
55-
56-
private <T extends AbstractStripeResponse<?>> T sendWithTelemetry(
57-
StripeRequest request, RequestSendFunction<T> send) throws StripeException {
58-
Optional<String> telemetryHeaderValue = requestTelemetry.getHeaderValue(request.headers());
59-
if (telemetryHeaderValue.isPresent()) {
60-
request =
61-
request.withAdditionalHeader(RequestTelemetry.HEADER_NAME, telemetryHeaderValue.get());
62-
}
63-
64-
Stopwatch stopwatch = Stopwatch.startNew();
65-
66-
T response = send.apply(request);
67-
68-
stopwatch.stop();
69-
70-
requestTelemetry.maybeEnqueueMetrics(response, stopwatch.getElapsed());
71-
72-
return response;
73-
}
74-
7551
/**
76-
* Sends the given request to Stripe's API, handling telemetry if not disabled.
77-
*
7852
* @param request the request
7953
* @return the response
8054
* @throws StripeException If the request fails for any reason
55+
* @deprecated Use {@link #request(StripeRequest)} instead.
8156
*/
57+
@Deprecated
8258
public StripeResponse requestWithTelemetry(StripeRequest request) throws StripeException {
83-
return sendWithTelemetry(request, this::request);
59+
return this.request(request);
8460
}
8561

8662
/**
87-
* Sends the given request to Stripe's API, streaming the response, and handling telemetry if not
88-
* disabled.
89-
*
9063
* @param request the request
9164
* @return the response
9265
* @throws StripeException If the request fails for any reason
66+
* @deprecated Use {@link #requestStream(StripeRequest)} instead.
9367
*/
68+
@Deprecated
9469
public StripeResponseStream requestStreamWithTelemetry(StripeRequest request)
9570
throws StripeException {
96-
return sendWithTelemetry(request, this::requestStream);
71+
return this.requestStream(request);
9772
}
9873

9974
public <T extends AbstractStripeResponse<?>> T sendWithRetries(
@@ -142,7 +117,7 @@ public <T extends AbstractStripeResponse<?>> T sendWithRetries(
142117
* @throws StripeException If the request fails for any reason
143118
*/
144119
public StripeResponse requestWithRetries(StripeRequest request) throws StripeException {
145-
return sendWithRetries(request, (r) -> this.requestWithTelemetry(r));
120+
return sendWithRetries(request, (r) -> this.request(r));
146121
}
147122

148123
/**
@@ -155,7 +130,7 @@ public StripeResponse requestWithRetries(StripeRequest request) throws StripeExc
155130
*/
156131
public StripeResponseStream requestStreamWithRetries(StripeRequest request)
157132
throws StripeException {
158-
return sendWithRetries(request, (r) -> this.requestStreamWithTelemetry(r));
133+
return sendWithRetries(request, (r) -> this.requestStream(r));
159134
}
160135

161136
/**

src/main/java/com/stripe/net/LiveStripeResponseGetter.java

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,40 @@
1212
import com.stripe.exception.oauth.UnsupportedResponseTypeException;
1313
import com.stripe.model.*;
1414
import com.stripe.model.oauth.OAuthError;
15+
import com.stripe.util.Stopwatch;
1516
import java.io.IOException;
1617
import java.io.InputStream;
1718
import java.lang.reflect.Type;
19+
import java.util.List;
1820
import java.util.Map;
21+
import java.util.Optional;
1922

2023
public class LiveStripeResponseGetter implements StripeResponseGetter {
2124
private final HttpClient httpClient;
2225
private final StripeResponseGetterOptions options;
2326

27+
private final RequestTelemetry requestTelemetry = new RequestTelemetry();
28+
29+
@FunctionalInterface
30+
private interface RequestSendFunction<R> {
31+
R apply(StripeRequest request) throws StripeException;
32+
}
33+
34+
private <T extends AbstractStripeResponse<?>> T sendWithTelemetry(
35+
StripeRequest request, List<String> usage, RequestSendFunction<T> send)
36+
throws StripeException {
37+
38+
Stopwatch stopwatch = Stopwatch.startNew();
39+
40+
T response = send.apply(request);
41+
42+
stopwatch.stop();
43+
44+
requestTelemetry.maybeEnqueueMetrics(response, stopwatch.getElapsed(), usage);
45+
46+
return response;
47+
}
48+
2449
/**
2550
* Initializes a new instance of the {@link LiveStripeResponseGetter} class with default
2651
* parameters.
@@ -46,17 +71,26 @@ public LiveStripeResponseGetter(StripeResponseGetterOptions options, HttpClient
4671
private StripeRequest toStripeRequest(ApiRequest apiRequest) throws StripeException {
4772
String fullUrl = fullUrl(apiRequest);
4873

49-
return new StripeRequest(
50-
apiRequest.getMethod(),
51-
fullUrl,
52-
apiRequest.getParams(),
53-
RequestOptions.merge(this.options, apiRequest.getOptions()));
74+
Optional<String> telemetryHeaderValue = requestTelemetry.pollPayload();
75+
StripeRequest request =
76+
new StripeRequest(
77+
apiRequest.getMethod(),
78+
fullUrl,
79+
apiRequest.getParams(),
80+
RequestOptions.merge(this.options, apiRequest.getOptions()));
81+
82+
if (telemetryHeaderValue.isPresent()) {
83+
request =
84+
request.withAdditionalHeader(RequestTelemetry.HEADER_NAME, telemetryHeaderValue.get());
85+
}
86+
return request;
5487
}
5588

5689
private StripeRequest toRawStripeRequest(RawApiRequest apiRequest) throws StripeException {
5790
String fullUrl = fullUrl(apiRequest);
5891

59-
StripeRequest stripeRequest =
92+
Optional<String> telemetryHeaderValue = requestTelemetry.pollPayload();
93+
StripeRequest request =
6094
StripeRequest.createWithStringContent(
6195
apiRequest.getMethod(),
6296
fullUrl,
@@ -65,9 +99,13 @@ private StripeRequest toRawStripeRequest(RawApiRequest apiRequest) throws Stripe
6599
apiRequest.getApiMode() == ApiMode.PREVIEW);
66100

67101
if (apiRequest.getApiMode() == ApiMode.PREVIEW) {
68-
return stripeRequest.withAdditionalHeader("Stripe-Version", Stripe.PREVIEW_API_VERSION);
102+
request = request.withAdditionalHeader("Stripe-Version", Stripe.PREVIEW_API_VERSION);
69103
}
70-
return stripeRequest;
104+
if (telemetryHeaderValue.isPresent()) {
105+
request =
106+
request.withAdditionalHeader(RequestTelemetry.HEADER_NAME, telemetryHeaderValue.get());
107+
}
108+
return request;
71109
}
72110

73111
@Override
@@ -76,7 +114,8 @@ public <T extends StripeObjectInterface> T request(ApiRequest apiRequest, Type t
76114
throws StripeException {
77115

78116
StripeRequest request = toStripeRequest(apiRequest);
79-
StripeResponse response = httpClient.requestWithRetries(request);
117+
StripeResponse response =
118+
sendWithTelemetry(request, apiRequest.getUsage(), r -> httpClient.requestWithRetries(r));
80119

81120
int responseCode = response.code();
82121
String responseBody = response.body();
@@ -106,7 +145,9 @@ public <T extends StripeObjectInterface> T request(ApiRequest apiRequest, Type t
106145
@Override
107146
public InputStream requestStream(ApiRequest apiRequest) throws StripeException {
108147
StripeRequest request = toStripeRequest(apiRequest);
109-
StripeResponseStream responseStream = httpClient.requestStreamWithRetries(request);
148+
StripeResponseStream responseStream =
149+
sendWithTelemetry(
150+
request, apiRequest.getUsage(), r -> httpClient.requestStreamWithRetries(r));
110151

111152
int responseCode = responseStream.code();
112153

src/main/java/com/stripe/net/RawApiRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public RawApiRequest(
1616
String rawContent,
1717
RawRequestOptions options,
1818
ApiMode apiMode) {
19-
super(baseAddress, method, path, options, apiMode);
19+
super(baseAddress, method, path, options, apiMode, null);
2020
this.rawContent = rawContent;
2121
this.options = options;
2222
}

src/main/java/com/stripe/net/RequestTelemetry.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import com.google.gson.annotations.SerializedName;
55
import com.stripe.Stripe;
66
import java.time.Duration;
7+
import java.util.ArrayList;
8+
import java.util.List;
79
import java.util.Optional;
810
import java.util.concurrent.ConcurrentLinkedQueue;
911
import lombok.Data;
@@ -26,12 +28,18 @@ class RequestTelemetry {
2628
* metrics, or if telemetry is disabled, then the returned {@code Optional} is empty.
2729
*
2830
* @param headers the request headers
31+
* @deprecated Use {$ling {@link #pollPayload()} instead.
2932
*/
33+
@Deprecated
3034
public Optional<String> getHeaderValue(HttpHeaders headers) {
3135
if (headers.firstValue(HEADER_NAME).isPresent()) {
3236
return Optional.empty();
3337
}
3438

39+
return this.pollPayload();
40+
}
41+
42+
public Optional<String> pollPayload() {
3543
RequestMetrics requestMetrics = prevRequestMetrics.poll();
3644
if (requestMetrics == null) {
3745
return Optional.empty();
@@ -45,14 +53,25 @@ public Optional<String> getHeaderValue(HttpHeaders headers) {
4553
return Optional.of(gson.toJson(payload));
4654
}
4755

56+
// TODO (major) remove this overload
57+
/**
58+
* @deprecated use {@link #maybeEnqueueMetrics(AbstractStripeResponse, Duration, List)} instead.
59+
*/
60+
@Deprecated
61+
public void maybeEnqueueMetrics(AbstractStripeResponse<?> response, Duration duration) {
62+
maybeEnqueueMetrics(response, duration, new ArrayList<String>());
63+
}
64+
4865
/**
4966
* If telemetry is enabled and the queue is not full, then enqueue a new metrics item; otherwise,
5067
* do nothing.
5168
*
5269
* @param response the Stripe response
5370
* @param duration the request duration
71+
* @param usage a list of tracked features used by the corresponding request
5472
*/
55-
public void maybeEnqueueMetrics(AbstractStripeResponse<?> response, Duration duration) {
73+
public void maybeEnqueueMetrics(
74+
AbstractStripeResponse<?> response, Duration duration, List<String> usage) {
5675
if (!Stripe.enableTelemetry) {
5776
return;
5877
}
@@ -65,7 +84,11 @@ public void maybeEnqueueMetrics(AbstractStripeResponse<?> response, Duration dur
6584
return;
6685
}
6786

68-
RequestMetrics metrics = new RequestMetrics(response.requestId(), duration.toMillis());
87+
if (usage != null && usage.size() == 0) {
88+
usage = null;
89+
}
90+
91+
RequestMetrics metrics = new RequestMetrics(response.requestId(), duration.toMillis(), usage);
6992
prevRequestMetrics.add(metrics);
7093
}
7194

@@ -82,5 +105,8 @@ private static class RequestMetrics {
82105

83106
@SerializedName("request_duration_ms")
84107
private final long requestDurationMs;
108+
109+
@SerializedName("usage")
110+
private final List<String> usage;
85111
}
86112
}

0 commit comments

Comments
 (0)