In the default sample Aspire project, I added the CosmosDB Hosting Package Aspire.Hosting.Azure.CosmosDB
in the AppHost, and the CosmosDB Component Aspire.Microsoft.Azure.Cosmos
in the ApiService. I then added logic to seed some data to the CosmosDB and read it back when hitting the /weatherforecast api.
If I hit the Weather page too soon after starting up, I typically get the following exception:
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.
Note! This led to a whopping big rabbithole because of the issues with running the CosmosDB emulator in a docker container, but basically the Aspire Hosting and Component do a good job of fixing up the container and connectionstring in the right way to have it actually work without needing to refer back to these older hacks.
AppHost
var cosmosDb = builder.AddAzureCosmosDB("cosmos")
.RunAsEmulator();
ApiService
builder.AddAzureCosmosClient("cosmos");
I got around avoiding the exception in the apiservice by calling the below method before app.Run()
.
internal static class CosmosExtensions
{
private class CosmosDB { }
internal static async Task CreateDatabaseAndContainer(this WebApplication app)
{
var logger = app.Services.GetRequiredService<ILogger<CosmosDB>>();
logger.LogInformation("Creating CosmosDB database and container");
var client = app.Services.GetRequiredService<CosmosClient>();
while (true)
{
try
{
await client.ReadAccountAsync();
break;
}
catch (HttpRequestException ex) when (ex.HttpRequestError is HttpRequestError.SecureConnectionError)
{
/* The CosmosDB emulator seems to take a very long time to start up, and returns this exception.
* System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.
*/
logger.LogWarning("CosmosDB connection retry");
Telemetry.CosmosDBConnectionRetries.Add(1);
await Task.Delay(1000);
}
}
logger.LogInformation("CosmosDB connection success");
Database database = await client.CreateDatabaseIfNotExistsAsync("Weather");
Container container = await database.CreateContainerIfNotExistsAsync("Cities", "/city", 400);
logger.LogInformation("CosmosDB container created");
}
}
But this feels like a terrible hack. I wonder what I might be missing?
The emulator takes a long time to start and returns SSL errors while it is starting up. I believe the Azure ComsosDB team is considering addressing the feedback with the current emulator.
Checkout the approach taken in https://github.com/dotnet/aspire-samples/pull/321.