Skip to content

Commit e8f663d

Browse files
authoredMay 19, 2024
Fix: watsonx.ai | refresh token issue and implement retry mechanism (#735)
* fix: refresh token only when needed and apply retry policy * fix: remove unused import
·
v1.0.0v1.0.0-M1
1 parent 09e122d commit e8f663d

File tree

1 file changed

+15
-4
lines changed
  • models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/api

1 file changed

+15
-4
lines changed
 

‎models/spring-ai-watsonx-ai/src/main/java/org/springframework/ai/watsonx/api/WatsonxAiApi.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
import java.util.function.Consumer;
2121

2222
import com.ibm.cloud.sdk.core.security.IamAuthenticator;
23+
import com.ibm.cloud.sdk.core.security.IamToken;
2324
import org.apache.commons.logging.Log;
2425
import org.apache.commons.logging.LogFactory;
26+
import org.springframework.retry.annotation.Backoff;
27+
import org.springframework.retry.annotation.Retryable;
2528
import reactor.core.publisher.Flux;
2629

2730
import org.springframework.ai.retry.RetryUtils;
@@ -50,6 +53,7 @@ public class WatsonxAiApi {
5053
private final String streamEndpoint;
5154
private final String textEndpoint;
5255
private final String projectId;
56+
private IamToken token;
5357

5458
/**
5559
* Create a new chat api.
@@ -72,6 +76,7 @@ public WatsonxAiApi(
7276
this.textEndpoint = textEndpoint;
7377
this.projectId = projectId;
7478
this.iamAuthenticator = IamAuthenticator.fromConfiguration(Map.of("APIKEY", IAMToken));
79+
this.token = this.iamAuthenticator.requestToken();
7580

7681
Consumer<HttpHeaders> defaultHeaders = headers -> {
7782
headers.setContentType(MediaType.APPLICATION_JSON);
@@ -88,27 +93,33 @@ public WatsonxAiApi(
8893
.build();
8994
}
9095

96+
@Retryable(retryFor = Exception.class, maxAttempts = 3, backoff = @Backoff(random = true, delay = 1200, maxDelay = 7000, multiplier = 2.5))
9197
public ResponseEntity<WatsonxAiResponse> generate(WatsonxAiRequest watsonxAiRequest) {
9298
Assert.notNull(watsonxAiRequest, WATSONX_REQUEST_CANNOT_BE_NULL);
9399

94-
String bearer = this.iamAuthenticator.requestToken().getAccessToken();
100+
if(this.token.needsRefresh()) {
101+
this.token = this.iamAuthenticator.requestToken();
102+
}
95103

96104
return this.restClient.post()
97105
.uri(this.textEndpoint)
98-
.header(HttpHeaders.AUTHORIZATION, "Bearer " + bearer)
106+
.header(HttpHeaders.AUTHORIZATION, "Bearer " + this.token.getAccessToken())
99107
.body(watsonxAiRequest.withProjectId(projectId))
100108
.retrieve()
101109
.toEntity(WatsonxAiResponse.class);
102110
}
103111

112+
@Retryable(retryFor = Exception.class, maxAttempts = 3, backoff = @Backoff(random = true, delay = 1200, maxDelay = 7000, multiplier = 2.5))
104113
public Flux<WatsonxAiResponse> generateStreaming(WatsonxAiRequest watsonxAiRequest) {
105114
Assert.notNull(watsonxAiRequest, WATSONX_REQUEST_CANNOT_BE_NULL);
106115

107-
String bearer = this.iamAuthenticator.requestToken().getAccessToken();
116+
if(this.token.needsRefresh()) {
117+
this.token = this.iamAuthenticator.requestToken();
118+
}
108119

109120
return this.webClient.post()
110121
.uri(this.streamEndpoint)
111-
.header(HttpHeaders.AUTHORIZATION, "Bearer " + bearer)
122+
.header(HttpHeaders.AUTHORIZATION, "Bearer " + this.token.getAccessToken())
112123
.bodyValue(watsonxAiRequest.withProjectId(this.projectId))
113124
.retrieve()
114125
.bodyToFlux(WatsonxAiResponse.class)

0 commit comments

Comments
 (0)
Please sign in to comment.