Skip to content

Commit 8aba82c

Browse files
authored
Add sync polling support to azure-core v2 (#44670)
* Add sync polling support to core-v2 * update javadocs * address pr comments * fix formatting
1 parent c3ffd25 commit 8aba82c

25 files changed

+2867
-1
lines changed

sdk/corev2/azure-core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
<dependency>
7676
<groupId>io.clientcore</groupId>
7777
<artifactId>core</artifactId>
78-
<version>1.0.0-beta.7</version> <!-- {x-version-update;io.clientcore:core;dependency} -->
78+
<version>1.0.0-beta.8</version> <!-- {x-version-update;unreleased_io.clientcore:core;dependency} -->
7979
</dependency>
8080

8181
<dependency>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.v2.core.http.polling;
5+
6+
import io.clientcore.core.http.models.Response;
7+
import io.clientcore.core.instrumentation.logging.ClientLogger;
8+
import io.clientcore.core.models.binarydata.BinaryData;
9+
10+
import java.lang.reflect.Type;
11+
import java.util.Collections;
12+
import java.util.List;
13+
import java.util.Objects;
14+
15+
/**
16+
* A polling strategy that chains multiple polling strategies, finds the first strategy that can
17+
* poll the current long-running operation, and polls with that strategy.
18+
*
19+
* @param <T> the type of the response type from a polling call, or BinaryData if raw response body should be kept
20+
* @param <U> the type of the final result object to deserialize into, or BinaryData if raw response body should be
21+
* kept
22+
*/
23+
public final class ChainedPollingStrategy<T, U> implements PollingStrategy<T, U> {
24+
private static final ClientLogger LOGGER = new ClientLogger(ChainedPollingStrategy.class);
25+
26+
private final List<PollingStrategy<T, U>> pollingStrategies;
27+
private PollingStrategy<T, U> pollableStrategy = null;
28+
29+
/**
30+
* Creates a chained polling strategy with a list of polling strategies.
31+
*
32+
* @param strategies the list of polling strategies
33+
* @throws NullPointerException If {@code strategies} is null.
34+
* @throws IllegalArgumentException If {@code strategies} is an empty list.
35+
*/
36+
public ChainedPollingStrategy(List<PollingStrategy<T, U>> strategies) {
37+
Objects.requireNonNull(strategies, "'strategies' cannot be null.");
38+
if (strategies.isEmpty()) {
39+
throw LOGGER.logThrowableAsError(new IllegalArgumentException("'strategies' cannot be empty."));
40+
}
41+
this.pollingStrategies = Collections.unmodifiableList(strategies);
42+
}
43+
44+
@Override
45+
public boolean canPoll(Response<BinaryData> initialResponse) {
46+
// Find the first strategy that can poll in series so that
47+
// pollableStrategy is only set once
48+
for (PollingStrategy<T, U> strategy : pollingStrategies) {
49+
if (strategy.canPoll(initialResponse)) {
50+
this.pollableStrategy = strategy;
51+
return true;
52+
}
53+
}
54+
55+
return false;
56+
}
57+
58+
/**
59+
* {@inheritDoc}
60+
*
61+
* @throws NullPointerException if {@link #canPoll(Response)} is not called prior to this, or if it returns false.
62+
*/
63+
@Override
64+
public U getResult(PollingContext<T> context, Type resultType) {
65+
return pollableStrategy.getResult(context, resultType);
66+
}
67+
68+
/**
69+
* {@inheritDoc}
70+
*
71+
* @throws NullPointerException if {@link #canPoll(Response)} is not called prior to this, or if it returns false.
72+
*/
73+
@Override
74+
public PollResponse<T> onInitialResponse(Response<BinaryData> response, PollingContext<T> pollingContext,
75+
Type pollResponseType) {
76+
return pollableStrategy.onInitialResponse(response, pollingContext, pollResponseType);
77+
}
78+
79+
/**
80+
* {@inheritDoc}
81+
*
82+
* @throws NullPointerException if {@link #canPoll(Response)} is not called prior to this, or if it returns false.
83+
*/
84+
@Override
85+
public PollResponse<T> poll(PollingContext<T> context, Type pollResponseType) {
86+
return pollableStrategy.poll(context, pollResponseType);
87+
}
88+
89+
/**
90+
* {@inheritDoc}
91+
*
92+
* @throws NullPointerException if {@link #canPoll(Response)} is not called prior to this, or if it returns false.
93+
*/
94+
@Override
95+
public T cancel(PollingContext<T> pollingContext, PollResponse<T> initialResponse) {
96+
return pollableStrategy.cancel(pollingContext, initialResponse);
97+
}
98+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.v2.core.http.polling;
5+
6+
import io.clientcore.core.http.models.Response;
7+
import io.clientcore.core.http.pipeline.HttpPipeline;
8+
import io.clientcore.core.models.binarydata.BinaryData;
9+
import io.clientcore.core.serialization.json.JsonSerializer;
10+
import io.clientcore.core.utils.Context;
11+
12+
import java.lang.reflect.Type;
13+
import java.util.Arrays;
14+
import java.util.Objects;
15+
16+
/**
17+
* The default polling strategy to use with Azure data plane services. The default polling strategy will
18+
* attempt three known strategies, {@link OperationResourcePollingStrategy}, {@link LocationPollingStrategy},
19+
* and {@link StatusCheckPollingStrategy}, in this order. The first strategy that can poll on the initial response
20+
* will be used. The created chained polling strategy is capable of handling most of the polling scenarios in Azure.
21+
*
22+
* @param <T> the type of the response type from a polling call, or BinaryData if raw response body should be kept
23+
* @param <U> the type of the final result object to deserialize into, or BinaryData if raw response body should be
24+
* kept
25+
*/
26+
public final class DefaultPollingStrategy<T, U> implements PollingStrategy<T, U> {
27+
private final ChainedPollingStrategy<T, U> chainedPollingStrategy;
28+
29+
/**
30+
* Creates a chained polling strategy with three known polling strategies,
31+
* {@link OperationResourcePollingStrategy}, {@link LocationPollingStrategy}, and
32+
* {@link StatusCheckPollingStrategy}, in this order, with a JSON serializer.
33+
*
34+
* @param httpPipeline an instance of {@link HttpPipeline} to send requests with
35+
* @throws NullPointerException If {@code httpPipeline} is null.
36+
*/
37+
public DefaultPollingStrategy(HttpPipeline httpPipeline) {
38+
this(httpPipeline, new JsonSerializer(), Context.none());
39+
}
40+
41+
/**
42+
* Creates a chained polling strategy with three known polling strategies,
43+
* {@link OperationResourcePollingStrategy}, {@link LocationPollingStrategy}, and
44+
* {@link StatusCheckPollingStrategy}, in this order, with a JSON serializer.
45+
*
46+
* @param httpPipeline an instance of {@link HttpPipeline} to send requests with
47+
* @param serializer a custom serializer for serializing and deserializing polling responses
48+
* @throws NullPointerException If {@code httpPipeline} is null.
49+
*/
50+
public DefaultPollingStrategy(HttpPipeline httpPipeline, JsonSerializer serializer) {
51+
this(httpPipeline, serializer, Context.none());
52+
}
53+
54+
/**
55+
* Creates a chained polling strategy with three known polling strategies,
56+
* {@link OperationResourcePollingStrategy}, {@link LocationPollingStrategy}, and
57+
* {@link StatusCheckPollingStrategy}, in this order, with a JSON serializer.
58+
*
59+
* @param httpPipeline an instance of {@link HttpPipeline} to send requests with
60+
* @param serializer a custom serializer for serializing and deserializing polling responses
61+
* @param context an instance of {@link Context}
62+
* @throws NullPointerException If {@code httpPipeline} is null.
63+
*/
64+
public DefaultPollingStrategy(HttpPipeline httpPipeline, JsonSerializer serializer, Context context) {
65+
this(httpPipeline, null, serializer, context);
66+
}
67+
68+
/**
69+
* Creates a chained polling strategy with three known polling strategies,
70+
* {@link OperationResourcePollingStrategy}, {@link LocationPollingStrategy}, and
71+
* {@link StatusCheckPollingStrategy}, in this order, with a JSON serializer.
72+
*
73+
* @param httpPipeline an instance of {@link HttpPipeline} to send requests with.
74+
* @param endpoint an endpoint for creating an absolute path when the path itself is relative.
75+
* @param serializer a custom serializer for serializing and deserializing polling responses.
76+
* @param context an instance of {@link Context}.
77+
* @throws NullPointerException If {@code httpPipeline} is null.
78+
*/
79+
public DefaultPollingStrategy(HttpPipeline httpPipeline, String endpoint, JsonSerializer serializer,
80+
Context context) {
81+
this.chainedPollingStrategy = new ChainedPollingStrategy<>(
82+
Arrays.asList(new OperationResourcePollingStrategy<>(httpPipeline, endpoint, serializer, null, context),
83+
new LocationPollingStrategy<>(httpPipeline, endpoint, serializer, context),
84+
new StatusCheckPollingStrategy<>(serializer)));
85+
}
86+
87+
/**
88+
* Creates a chained polling strategy with 3 known polling strategies, {@link OperationResourcePollingStrategy},
89+
* {@link LocationPollingStrategy}, and {@link StatusCheckPollingStrategy}, in this order, with a custom
90+
* serializer.
91+
*
92+
* @param pollingStrategyOptions options to configure this polling strategy.
93+
* @throws NullPointerException If {@code pollingStrategyOptions} is null.
94+
*/
95+
public DefaultPollingStrategy(PollingStrategyOptions pollingStrategyOptions) {
96+
Objects.requireNonNull(pollingStrategyOptions, "'pollingStrategyOptions' cannot be null");
97+
this.chainedPollingStrategy = new ChainedPollingStrategy<>(
98+
Arrays.asList(new OperationResourcePollingStrategy<>(null, pollingStrategyOptions),
99+
new LocationPollingStrategy<>(pollingStrategyOptions),
100+
new StatusCheckPollingStrategy<>(pollingStrategyOptions.getSerializer())));
101+
}
102+
103+
@Override
104+
public U getResult(PollingContext<T> pollingContext, Type resultType) {
105+
return chainedPollingStrategy.getResult(pollingContext, resultType);
106+
}
107+
108+
@Override
109+
public boolean canPoll(Response<BinaryData> initialResponse) {
110+
return chainedPollingStrategy.canPoll(initialResponse);
111+
}
112+
113+
@Override
114+
public PollResponse<T> onInitialResponse(Response<BinaryData> response, PollingContext<T> pollingContext,
115+
Type pollResponseType) {
116+
return chainedPollingStrategy.onInitialResponse(response, pollingContext, pollResponseType);
117+
}
118+
119+
@Override
120+
public PollResponse<T> poll(PollingContext<T> pollingContext, Type pollResponseType) {
121+
return chainedPollingStrategy.poll(pollingContext, pollResponseType);
122+
}
123+
124+
@Override
125+
public T cancel(PollingContext<T> pollingContext, PollResponse<T> initialResponse) {
126+
return chainedPollingStrategy.cancel(pollingContext, initialResponse);
127+
}
128+
}

0 commit comments

Comments
 (0)