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");
using var activity = Telemetry.ActivitySource.StartActivity("CreateDatabaseAndContainer Activity");
Database database = await client.CreateDatabaseIfNotExistsAsync("Weather");
activity?.AddEvent(new ActivityEvent("CosmosDB Database Created"));
Container container = await database.CreateContainerIfNotExistsAsync("Cities", "/city", 400);
activity?.AddEvent(new ActivityEvent("CosmosDB Container Created"));
logger.LogInformation("CosmosDB container created");
}
}
But this feels like a terrible hack. I wonder what I might be missing?