Due to company's policy, our CosmosDb keys are rotated periodically with the new keys in Azure KeyVault so we need to deal with this changing key in our Java weblfux/reactive application. From Java SDK, once a CosmosAsyncClient is created from master key there is no way to change it and we need to rebuild it with roughly the following code:
SecretAsyncClient secretAsyncClient = new SecretClientBuilder().buildAsyncClient()
...
Mono<CosmosAsyncClient> client = secretAsyncClient.getSecret(KEY_NAME).map(
s -> s.getValue()
).map(
key -> new CosmosClientBuilder()
.endpoint(HOST)
.key(key)
.buildAsyncClient()
);
return client.flatMap(
...
);
From the log, the getSecret()
is OK but then I got:
05:25:00.597 INFO c.a.c.i.RxDocumentClientImpl - Initializing DocumentClient [4] with serviceEndpoint [https://xxxx-cosmosdb-sql-dev.documents.azure.com:443/], connectionPolicy [ConnectionPolicy{httpNetworkRequestTimeout=PT1M, tcpNetworkRequestTimeout=PT5S, connectionMode=DIRECT, maxConnectionPoolSize=1000, idleHttpConnectionTimeout=PT1M, idleTcpConnectionTimeout=PT0S, userAgentSuffix='', throttlingRetryOptions=RetryOptions{maxRetryAttemptsOnThrottledRequests=9, maxRetryWaitTime=PT30S}, endpointDiscoveryEnabled=true, preferredRegions=[Switzerland North], multipleWriteRegionsEnabled=true, proxyType=null, inetSocketProxyAddress=null, readRequestsFallbackEnabled=true, connectTimeout=PT5S, idleTcpEndpointTimeout=PT1H, maxConnectionsPerEndpoint=130, maxRequestsPerConnection=30, tcpConnectionEndpointRediscoveryEnabled=true}], consistencyLevel [Session], directModeProtocol [Tcp]05:25:00.598 ERROR c.a.c.i.RxDocumentClientImpl - unexpected failure in initializing client.
java.lang.RuntimeException: java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-epoll-3
at com.azure.cosmos.implementation.http.ReactorNettyClient.attemptToWarmupHttpClient(ReactorNettyClient.java:118)
at com.azure.cosmos.implementation.http.ReactorNettyClient.createWithConnectionProvider(ReactorNettyClient.java:98)
at com.azure.cosmos.implementation.http.HttpClient.createFixed(HttpClient.java:61)
at com.azure.cosmos.implementation.RxDocumentClientImpl.httpClient(RxDocumentClientImpl.java:617)
at com.azure.cosmos.implementation.RxDocumentClientImpl.<init>(RxDocumentClientImpl.java:410)
at com.azure.cosmos.implementation.RxDocumentClientImpl.<init>(RxDocumentClientImpl.java:262)
at com.azure.cosmos.implementation.RxDocumentClientImpl.<init>(RxDocumentClientImpl.java:230)
at com.azure.cosmos.implementation.AsyncDocumentClient$Builder.build(AsyncDocumentClient.java:243)
at com.azure.cosmos.CosmosAsyncClient.<init>(CosmosAsyncClient.java:129)
at com.azure.cosmos.CosmosClientBuilder.buildAsyncClient(CosmosClientBuilder.java:779)
So it seems that I need to put the CosmosClientBuilder().buildAsyncClient()
part to an executor pool? Is there any simpler or more elegant way to do this?
As I explained here, Cosmos DB SDK client creates a lot of connections because of the nature of distributed systems. Warmup is a functionality that needs to be implemented in the client creation.
Regarding your original problem of rotating keys, I provided the details here - https://github.com/Azure/azure-sdk-for-java/issues/40051#issuecomment-2097118239
You can use AzureKeyCredential interface which allows to rotate the keys without the need for re-creating the client every time. https://azuresdkdocs.blob.core.windows.net/$web/java/azure-cosmos/latest/com/azure/cosmos/CosmosClientBuilder.html#credential(com.azure.core.credential.AzureKeyCredential)