什么是无效的单声道值无效的方法?

发布于 2025-02-11 23:32:18 字数 1642 浏览 0 评论 0原文

我会尽力解释我的用例。在我的应用程序中调用外部Web服务之前,我请使用Spring WebFlux WebClient向代币提供商提供OAuth访问令牌,并且我正在缓存该值,以便下次需要它。每当请求失败使用错误代码401时,我都想用新令牌重试缓存并重试。

一切正常,接受我不确定单声道的缓存无效。

如果需要使缓存无效,则将存储在布尔变量中是个好主意吗?在订阅Auth Mono时重试时,无效的缓存谓词将是正确的,这将无效缓存,并将完成新的请求。

还有其他想法吗?

示例代码:

@Component
public class AccessTokenService {

    private final WebClient accessTokenClient;
    private final Mono<Token> accessTokenMono;
    private final AtomicBoolean cacheInvalidated = new AtomicBoolean();

    public AccessTokenService() {
        accessTokenClient = WebClient.builder()
                .baseUrl("example-token-uri")
                .build();

        accessTokenMono = initAccessTokenMono();
    }

    private Mono<Token> initAccessTokenMono() {
        return accessTokenClient.post()
                .uri(uriBuilder -> uriBuilder
                        // Some credentials as parameters
                        .build())
                .retrieve()
                .bodyToMono(Token.class)
                // Always set cache invalidated to false when we get the response
                .doOnSuccess(token -> cacheInvalidated.set(false))
                .cacheInvalidateIf(accessToken -> cacheInvalidated.get());
    }

    public Mono<Token> getAccessTokenMono() {
        // Shared for all requests
        return accessTokenMono;
    }

// Called on 401
    public void setCacheInvalidated() {
        // Sets the predicate to true. For the next subscription the cache will be invalidated and a new request to the token provider will occur
        cacheInvalidated.set(true);
    }
}

I'll try to explain my use case as easy as possible. Before I call an external web service in my application I'm requesting an oauth access token from a token provider using the Spring Webflux WebClient and I'm caching the value so it's reused for the next time I need it. Whenever a request fails with error code 401 I want to invalidate the cache and retry with a new token.

Everything works fine accept that I'm not sure about the cache invalidation of the Mono.

Is it a good idea to store in a boolean variable if the cache needs to be invalidated? On retry when subscribing to the auth Mono the invalidating cache predicate will be true which will invalidate the cache and a new request will be done.

Any other ideas?

Sample code:

@Component
public class AccessTokenService {

    private final WebClient accessTokenClient;
    private final Mono<Token> accessTokenMono;
    private final AtomicBoolean cacheInvalidated = new AtomicBoolean();

    public AccessTokenService() {
        accessTokenClient = WebClient.builder()
                .baseUrl("example-token-uri")
                .build();

        accessTokenMono = initAccessTokenMono();
    }

    private Mono<Token> initAccessTokenMono() {
        return accessTokenClient.post()
                .uri(uriBuilder -> uriBuilder
                        // Some credentials as parameters
                        .build())
                .retrieve()
                .bodyToMono(Token.class)
                // Always set cache invalidated to false when we get the response
                .doOnSuccess(token -> cacheInvalidated.set(false))
                .cacheInvalidateIf(accessToken -> cacheInvalidated.get());
    }

    public Mono<Token> getAccessTokenMono() {
        // Shared for all requests
        return accessTokenMono;
    }

// Called on 401
    public void setCacheInvalidated() {
        // Sets the predicate to true. For the next subscription the cache will be invalidated and a new request to the token provider will occur
        cacheInvalidated.set(true);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冬天旳寂寞 2025-02-18 23:32:18

与其尝试将肮脏标志的状态与mono的有效性保持同步,为什么不在检测401时简单地交换新的mono?我还通过cache()定期刷新令牌,但这并不是您尝试做的事情。

@Component
public class AccessTokenService {
    private static final Duration TOKEN_REFRESH_INTERVAL = Duration.ofHours(1);
    private final WebClient accessTokenClient;
    private final AtomicReference<Mono<Token>> accessTokenMono = new AtomicReference<>();

    public AccessTokenService() {
        accessTokenClient = WebClient.builder()
            .baseUrl("example-token-uri")
            .build();

        accessTokenMono.set(initAccessTokenMono());
    }

    private Mono<Token> initAccessTokenMono() {
        return accessTokenClient.post()
            .uri(uriBuilder -> uriBuilder
                // Some credentials as parameters
                .build())
            .retrieve()
            .bodyToMono(Token.class)
            .cache(token -> TOKEN_REFRESH_INTERVAL,         // refresh every interval
                exc -> Duration.ZERO, () -> Duration.ZERO); // don't cache exceptions or empties
    }

    public Mono<Token> getAccessTokenMono() {
        // Shared for all requests
        return accessTokenMono.get();
    }

    // Called on 401
    public void setCacheInvalidated() {
        // Plug in a new Mono so subsequent requests get a new token
        accessTokenMono.set(initAccessTokenMono());
    }
}

Instead of attempting to keep the state of a dirty flag in sync with the validity of the Mono, why not simply swap in a new Mono when you detect a 401? I'm also having it refresh the token periodically via cache(), but that's not explicitly required for what you're trying to do.

@Component
public class AccessTokenService {
    private static final Duration TOKEN_REFRESH_INTERVAL = Duration.ofHours(1);
    private final WebClient accessTokenClient;
    private final AtomicReference<Mono<Token>> accessTokenMono = new AtomicReference<>();

    public AccessTokenService() {
        accessTokenClient = WebClient.builder()
            .baseUrl("example-token-uri")
            .build();

        accessTokenMono.set(initAccessTokenMono());
    }

    private Mono<Token> initAccessTokenMono() {
        return accessTokenClient.post()
            .uri(uriBuilder -> uriBuilder
                // Some credentials as parameters
                .build())
            .retrieve()
            .bodyToMono(Token.class)
            .cache(token -> TOKEN_REFRESH_INTERVAL,         // refresh every interval
                exc -> Duration.ZERO, () -> Duration.ZERO); // don't cache exceptions or empties
    }

    public Mono<Token> getAccessTokenMono() {
        // Shared for all requests
        return accessTokenMono.get();
    }

    // Called on 401
    public void setCacheInvalidated() {
        // Plug in a new Mono so subsequent requests get a new token
        accessTokenMono.set(initAccessTokenMono());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文