New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve CosmosClient initialization ergonomics #4405
base: master
Are you sure you want to change the base?
Conversation
Both the async and the callers needs to wait. Is the challenge here about calling async over sync? At-least the factory pattern is guaranteeing
Overall there is very little value with the side-affect of initialization called multiples. |
@kirankumarkolli Not sure what you mean by this? I don't believe the SDK cares; you can grab things from containers while this initialize function is still going on. I've been struggling to think of another Microsoft SDK that has something like this; an async factory method to initialize the client. This should be done in the background, and this PR gives the user' that opportunity, it doesn't prescribe an opinionated way of how to do it. Take EntityFramework as an example; it has extension methods to add the DbContext to the servicebuilder; where is the async The cosmos SDK's
Which is it? |
Let me try to chip in here and see if I can shed some light into the topic. The reason
If your application can handle this, which means that you are fine paying the cost of initialization during data plane calls, then why not simply create a client instance and let data plane initialize it, paying the latency cost hit at that time? Because that is what will happen if you ignore and not await the initialization, right? Triggering the initialization as a background process does not ensure anything (that the initialization completes successfully and when), so what's the point? |
Then it should be sync, not async
This PR leaves it up to the implementer to decide what is best for their scenario. The application can still hold off until the the client is fully initialized by awaiting the result. If you don't pre-initialize ALL your containers, then EVERY operation that happens that accesses an uninitialized container will have to pay that cost on first-run. If you have a This just gives you more choices. |
Can you expand on that? Initialization requires I/O calls, they are async by nature. If the method is sync then it would block the threads during those executions? You can make it sync if you want with |
The point is that this freedom exists today already. Create the client and move on or await the CreateAndInitialize. Either you need the client to be fully initialized or you don't. The proposed API and usage of it in this PR is simply doing a background initialization that might or might not benefit the data plane calls that the application does afterwards. With that level of uncertainty in the outcome, what's the benefit? |
Would achieve the same, a background initialization of the connections with no guarantees. |
@ealsur only for a single container. Suppose you have 10 API endpoints, one for each of 10 containers; you can either pay the cost once very early on in the application's lifecycle, or you can pay it 10 times, one for every time a new container is called.
Agreeing/disagreeing with this PR essentially comes down to three viewpoints:
The view of the members here appears to fall under 2. |
With current public API, few ways applications can achieve the goals are Lazy initialization:
// Initialization/Startup block
CosmosClient client = new CosmosClient();
// Data flows
var result = await client.GetContainer(database, container).ReadItemAsync(); It's also possible for startup/initialization to hold the Container object as well. Pre-initialize clients:
Option1: // Initialization/Startup block
IReadOnlyList<(string databaseId, string containerId)> containers = ...;
CosmosClient client = new CosmosClient.CreateAndInitializeAsync(, containers);
// Data flows
var result = await client.GetContainer(database, container).ReadItemAsync(); Option2: // Initialization/Startup block
CosmosClientBuilder clientBuilder = new CosmosClientBuilder();
IReadOnlyList<(string databaseId, string containerId)> containers = ...;
// Async startup
CosmosClient client = await clientBuilder.BuildAndInitializeAsync(containers);
// Sync startup
CosmosClient client = clientBuilder.BuildAndInitializeAsync(containers).Result;
// Data flows
var result = await client.GetContainer(database, container).ReadItemAsync(); Overall the application developers can achieve both scenarios. The one possible corner scenario is creating client sync but application initialize it in background. This model is also non-deterministic in behavior the application. We would like to understand this better if this what is referred above. |
Pull Request Template
Description
Improves real-world ergonomics over using
CreateAndInitializeAsync
, by makingInitializeContainersAsync
public.A better option would be
Type of change
Please delete options that are not relevant.
Closing issues
To automatically close an issue: closes #4404