@@ -36,6 +36,8 @@ type TestHostState =
3636module AspireTestHost =
3737
3838 let private graceServerResourceName = " grace-server"
39+ let private azuriteResourceName = " azurite"
40+ let private serviceBusSqlResourceName = " servicebus-sql"
3941 let private serviceBusEmulatorResourceName = " servicebus-emulator"
4042 let private isCi =
4143 match Environment.GetEnvironmentVariable( " GITHUB_ACTIONS" ), Environment.GetEnvironmentVariable( " CI" ) with
@@ -61,6 +63,12 @@ module AspireTestHost =
6163 |> Seq.tryFind ( fun resource -> resource :? 'T)
6264 |> Option.map ( fun resource -> resource.Name)
6365
66+ let private tryFindResourceByName ( app : DistributedApplication ) ( resourceName : string ) =
67+ let model = app.Services.GetRequiredService< DistributedApplicationModel>()
68+
69+ model.Resources
70+ |> Seq.tryFind ( fun resource -> resource.Name = resourceName)
71+
6472 let private getEndpointName ( app : DistributedApplication ) ( resourceName : string ) =
6573 let resource = getResource app resourceName
6674 let resourceWithEndpoints = resource :?> IResourceWithEndpoints
@@ -374,9 +382,47 @@ module AspireTestHost =
374382
375383 ready <- true
376384 with
385+ | ex ->
386+ lastError <- ex.Message
387+ do ! Task.Delay( TimeSpan.FromSeconds( 1.0 ))
388+ }
389+
390+ let private waitForGraceServerHttpReadyAsync ( client : HttpClient ) ( ct : CancellationToken ) =
391+ task {
392+ let perRequestTimeout = getTimeout ( TimeSpan.FromSeconds( 10.0 )) ( TimeSpan.FromSeconds( 20.0 ))
393+ let sw = Stopwatch.StartNew()
394+ let mutable attempt = 0
395+ let mutable lastError = String.Empty
396+
397+ Console.WriteLine( $" Waiting for Grace.Server HTTP readiness at {client.BaseAddress}..." )
398+
399+ let rec loop () =
400+ task {
401+ if ct.IsCancellationRequested then
402+ raise ( TimeoutException( $" Timed out waiting for Grace.Server HTTP readiness. Last error: {lastError}" ))
403+
404+ attempt <- attempt + 1
405+
406+ try
407+ use linkedCts = CancellationTokenSource.CreateLinkedTokenSource( ct)
408+ linkedCts.CancelAfter( perRequestTimeout)
409+
410+ use! response = client.GetAsync( " /healthz" , linkedCts.Token)
411+
412+ if response.IsSuccessStatusCode then
413+ Console.WriteLine( $" Grace.Server HTTP readiness confirmed after {sw.Elapsed.TotalSeconds:n1}s (attempt {attempt})." )
414+ else
415+ lastError <- $" Status {(int response.StatusCode)} {response.StatusCode}"
416+ do ! Task.Delay( TimeSpan.FromSeconds( 1.0 ), ct)
417+ return ! loop ()
418+ with
377419 | ex ->
378420 lastError <- ex.Message
379- do ! Task.Delay( TimeSpan.FromSeconds( 1.0 ))
421+ do ! Task.Delay( TimeSpan.FromSeconds( 1.0 ), ct)
422+ return ! loop ()
423+ }
424+
425+ do ! loop ()
380426 }
381427
382428 let startAsync () =
@@ -407,6 +453,18 @@ module AspireTestHost =
407453
408454 use cts = new CancellationTokenSource( defaultWaitTimeout)
409455
456+ match tryFindResourceByName app azuriteResourceName with
457+ | Some _ ->
458+ Console.WriteLine( $" Azurite resource detected: {azuriteResourceName}" )
459+ do ! waitForResourceHealthyAsync notificationService app azuriteResourceName cts.Token
460+ | None -> Console.WriteLine( " Azurite resource not found in model." )
461+
462+ match tryFindResourceByName app serviceBusSqlResourceName with
463+ | Some _ ->
464+ Console.WriteLine( $" Service Bus SQL resource detected: {serviceBusSqlResourceName}" )
465+ do ! waitForResourceHealthyAsync notificationService app serviceBusSqlResourceName cts.Token
466+ | None -> Console.WriteLine( " Service Bus SQL resource not found in model." )
467+
410468 match tryFindResourceName< AzureCosmosDBEmulatorResource> app with
411469 | Some name ->
412470 Console.WriteLine( $" Cosmos emulator resource detected: {name}" )
@@ -501,6 +559,9 @@ module AspireTestHost =
501559 let endpointName = getEndpointName app graceServerResourceName
502560 let endpointUri = app.GetEndpoint( graceServerResourceName, endpointName)
503561 let client = app.CreateHttpClient( graceServerResourceName, endpointName)
562+ client.Timeout <- getTimeout ( TimeSpan.FromSeconds( 100.0 )) ( TimeSpan.FromMinutes( 5.0 ))
563+
564+ do ! waitForGraceServerHttpReadyAsync client cts.Token
504565
505566 let diagnosticsPath = Path.Combine( Path.GetTempPath(), " grace-server-tests.host.log" )
506567
0 commit comments