Я получаю доступ к внешнему API для отдыха, который защищен с помощью OpenID connect.Я должен запустить работу, которая вызывает API несколько раз, прежде чем он завершится.Это задание может выполняться параллельно с использованием нескольких параллельных потоков.Таким образом, я использую сервис для доступа к API, который создается для каждого задания:
private AccessAndRefresTokens tokens; // I initially get that from somewhere else
public Mono<Result> callTheApi(){
return createWebClientWith(tokens.accessToken).executeRequest();
}
public Mono<Result> callOtherApiFunction(){
return createWebClientWith(tokens.accessToken).executeRequest();
}
public Mono<Result> callYetAnotherApiFunction(){
return createWebClientWith(tokens.accessToken).executeRequest();
}
Когда мое задание выполняется, может случиться, что токен доступа истекает между двумя вызовами API.Чтобы этого не происходило, я хотел бы проверять действительность токена доступа перед каждым запросом и обновлять его при необходимости.
Моя первая идея состояла в том, чтобы проверить правильность внутри оператора flatMap:
Mono.just(tokens).flatMap(tokens -> {
if(accessTokenExpired){
return refreshAccessToken().doOnNext(refreshedTokens -> tokens = refreshedTokens);
}else{
return Mono.just(tokens.accessToken);
}
}).flatMap(accessToken -> createWebClientWith(accessToken));
Однако мне кажется, что это вызовет обновление несколько раз, если несколько потоков обращаются к службе, и обновление еще не завершено.Как следствие, я бы закончил тем, что обновил токен доступа несколько раз за очень короткое время, которое могло бы потерпеть неудачу из-за ограничений скорости.не желаемый вариант.Поэтому я попытался что-то выяснить, используя реактор Processor
, но я не смог найти удовлетворительное решение.
Так есть ли способ гарантировать, что маркер доступа передается только один раз?И как мне добиться этого без использования кода блокировки?