@@ -72,16 +72,16 @@ public static IResourceBuilder<SurrealDbServerResource> AddSurrealServer(
7272        { 
7373            args . Add ( "--strict" ) ; 
7474        } 
75-          
75+ 
7676        // The password must be at least 8 characters long and contain characters from three of the following four sets: Uppercase letters, Lowercase letters, Base 10 digits, and Symbols 
7777        var  passwordParameter  =  password ? . Resource  ??  ParameterResourceBuilderExtensions . CreateDefaultPasswordParameter ( builder ,  $ "{ name } -password",  minLower :  1 ,  minUpper :  1 ,  minNumeric :  1 ) ; 
7878
7979        string  imageTag  =  builder . ExecutionContext . IsRunMode 
8080            ?  $ "{ SurrealDbContainerImageTags . Tag } -dev"
8181            :  SurrealDbContainerImageTags . Tag ; 
82-          
82+ 
8383        var  surrealServer  =  new  SurrealDbServerResource ( name ,  userName ? . Resource ,  passwordParameter ) ; 
84-          
84+ 
8585        return  builder . AddResource ( surrealServer ) 
8686                      . WithEndpoint ( port :  port ,  targetPort :  SurrealDbPort ,  name :  SurrealDbServerResource . PrimaryEndpointName ) 
8787                      . WithImage ( SurrealDbContainerImageTags . Image ,  imageTag ) 
@@ -99,42 +99,65 @@ public static IResourceBuilder<SurrealDbServerResource> AddSurrealServer(
9999                          { 
100100                              return ; 
101101                          } 
102-                            
102+ 
103103                          var  connectionString  =  await  surrealServer . GetConnectionStringAsync ( ct ) . ConfigureAwait ( false ) ; 
104104                          if  ( connectionString  is  null ) 
105105                          { 
106106                              throw  new  DistributedApplicationException ( $ "ResourceReadyEvent was published for the '{ surrealServer . Name } ' resource but the connection string was null.") ; 
107107                          } 
108-                           
109-                           var  options  =  new  SurrealDbOptionsBuilder ( ) . FromConnectionString ( connectionString ) . Build ( ) ; 
110-                           await  using  var  surrealClient  =  new  SurrealDbClient ( options ) ; 
111-                           
112-                           foreach  ( var  nsResourceName  in  surrealServer . Namespaces . Keys ) 
113-                           { 
114-                               if  ( builder . Resources . FirstOrDefault ( n => 
115-                                       string . Equals ( n . Name ,  nsResourceName ,  StringComparison . OrdinalIgnoreCase ) )  is 
116-                                   SurrealDbNamespaceResource  surrealDbNamespace ) 
117-                               { 
118-                                   await  CreateNamespaceAsync ( surrealClient ,  surrealDbNamespace ,  @event . Services ,  ct ) 
119-                                       . ConfigureAwait ( false ) ; 
120-                               
121-                                   await  surrealClient . Use ( surrealDbNamespace . NamespaceName ,  null ! ,  ct ) . ConfigureAwait ( false ) ; 
122-                           
123-                                   foreach  ( var  dbResourceName  in  surrealDbNamespace . Databases . Keys ) 
124-                                   { 
125-                                       if  ( builder . Resources . FirstOrDefault ( n => 
126-                                               string . Equals ( n . Name ,  dbResourceName ,  StringComparison . OrdinalIgnoreCase ) )  is 
127-                                           SurrealDbDatabaseResource  surrealDbDatabase ) 
128-                                       { 
129-                                           await  CreateDatabaseAsync ( surrealClient ,  surrealDbDatabase ,  @event . Services ,  ct ) 
130-                                               . ConfigureAwait ( false ) ; 
131-                                       } 
132-                                   } 
133-                               } 
134-                           } 
108+ 
109+                           await  EnsuresNsDbCreated ( builder ,  connectionString ,  surrealServer ,  @event . Services ,  ct ) ; 
135110                      } ) ; 
136111    } 
137112
113+     private  static   async  Task  EnsuresNsDbCreated ( 
114+         IDistributedApplicationBuilder  builder , 
115+         string  connectionString , 
116+         SurrealDbServerResource  surrealServer , 
117+         IServiceProvider  services , 
118+         CancellationToken  ct 
119+     ) 
120+     { 
121+         var  options  =  new  SurrealDbOptionsBuilder ( ) . FromConnectionString ( connectionString ) . Build ( ) ; 
122+         await  using  var  surrealClient  =  new  SurrealDbClient ( options ) ; 
123+ 
124+         foreach  ( var  nsResourceName  in  surrealServer . Namespaces . Keys ) 
125+         { 
126+             if  ( builder . Resources . FirstOrDefault ( n => 
127+                     string . Equals ( n . Name ,  nsResourceName ,  StringComparison . OrdinalIgnoreCase ) )  is 
128+                 SurrealDbNamespaceResource  surrealDbNamespace ) 
129+             { 
130+                 await  CreateNamespaceAsync ( surrealClient ,  surrealDbNamespace ,  services ,  ct ) 
131+                     . ConfigureAwait ( false ) ; 
132+ 
133+                 // 💡 Wait until the Namespace is really created?! 
134+                 while  ( ! ct . IsCancellationRequested ) 
135+                 { 
136+                     try 
137+                     { 
138+                         await  surrealClient . Use ( surrealDbNamespace . NamespaceName ,  null ! ,  ct ) . ConfigureAwait ( false ) ; 
139+                         break ; 
140+                     } 
141+                     catch 
142+                     { 
143+                         await  Task . Delay ( 200 ,  ct ) . ConfigureAwait ( false ) ; 
144+                     } 
145+                 } 
146+ 
147+                 foreach  ( var  dbResourceName  in  surrealDbNamespace . Databases . Keys ) 
148+                 { 
149+                     if  ( builder . Resources . FirstOrDefault ( n => 
150+                             string . Equals ( n . Name ,  dbResourceName ,  StringComparison . OrdinalIgnoreCase ) )  is 
151+                         SurrealDbDatabaseResource  surrealDbDatabase ) 
152+                     { 
153+                         await  CreateDatabaseAsync ( surrealClient ,  surrealDbDatabase ,  services ,  ct ) 
154+                             . ConfigureAwait ( false ) ; 
155+                     } 
156+                 } 
157+             } 
158+         } 
159+     } 
160+ 
138161    /// <summary> 
139162    /// Adds a SurrealDB namespace to the application model. This is a child resource of a <see cref="SurrealDbServerResource"/>. 
140163    /// </summary> 
@@ -174,7 +197,7 @@ public static IResourceBuilder<SurrealDbNamespaceResource> AddNamespace(
174197        var  surrealServerNamespace  =  new  SurrealDbNamespaceResource ( name ,  namespaceName ,  builder . Resource ) ; 
175198        return  builder . ApplicationBuilder . AddResource ( surrealServerNamespace ) ; 
176199    } 
177-      
200+ 
178201    /// <summary> 
179202    /// Defines the SQL script used to create the namespace. 
180203    /// </summary> 
@@ -232,38 +255,34 @@ public static IResourceBuilder<SurrealDbDatabaseResource> AddDatabase(
232255        builder . Resource . AddDatabase ( name ,  databaseName ) ; 
233256        var  surrealServerDatabase  =  new  SurrealDbDatabaseResource ( name ,  databaseName ,  builder . Resource ) ; 
234257
235-         SurrealDbClient ?  surrealDbClient  =  null ; 
236- 
237-         builder . ApplicationBuilder . Eventing . Subscribe < ConnectionStringAvailableEvent > ( surrealServerDatabase ,  async  ( @event ,  ct )  => 
238-         { 
239-             var  connectionString  =  await  surrealServerDatabase . ConnectionStringExpression . GetValueAsync ( ct ) . ConfigureAwait ( false ) ; 
240-             if  ( connectionString  is  null ) 
241-             { 
242-                 throw  new  DistributedApplicationException ( $ "ConnectionStringAvailableEvent was published for the '{ surrealServerDatabase } ' resource but the connection string was null.") ; 
243-             } 
244- 
245-             var  options  =  new  SurrealDbOptionsBuilder ( ) . FromConnectionString ( connectionString ) . Build ( ) ; 
246-             surrealDbClient  =  new  SurrealDbClient ( options ) ; 
247-         } ) ; 
258+         SurrealDbOptions ?  surrealDbOptions  =  null ; 
248259
249260        string  namespaceName  =  builder . Resource . Name ; 
250261        string  serverName  =  builder . Resource . Parent . Name ; 
251262
252263        string  healthCheckKey  =  $ "{ serverName } _{ namespaceName } _{ name } _check"; 
253-         // TODO : Bug to be fixed 
254-         //builder.ApplicationBuilder.Services.AddHealthChecks().AddSurreal(_ => surrealDbClient!, healthCheckKey); 
255264        builder . ApplicationBuilder . Services . AddHealthChecks ( ) . Add ( new  HealthCheckRegistration ( 
256265                name :  healthCheckKey , 
257-                 _  =>  new  SurrealDbHealthCheck ( surrealDbClient ! ) , 
266+                 sp  =>  new  SurrealDbHealthCheck ( surrealDbOptions ! ,   sp . GetRequiredService < ILogger < SurrealDbHealthCheck > > ( ) ) , 
258267                failureStatus :  null , 
259268                tags :  null 
260269            ) 
261270        ) ; 
262-          
271+ 
263272        return  builder . ApplicationBuilder . AddResource ( surrealServerDatabase ) 
264-             . WithHealthCheck ( healthCheckKey ) ; 
273+             . WithHealthCheck ( healthCheckKey ) 
274+             . OnConnectionStringAvailable ( async  ( _ ,  _ ,  ct )  => 
275+             { 
276+                 var  connectionString  =  await  surrealServerDatabase . ConnectionStringExpression . GetValueAsync ( ct ) . ConfigureAwait ( false ) ; 
277+                 if  ( connectionString  is  null ) 
278+                 { 
279+                     throw  new  DistributedApplicationException ( $ "ConnectionStringAvailableEvent was published for the '{ surrealServerDatabase } ' resource but the connection string was null.") ; 
280+                 } 
281+ 
282+                 surrealDbOptions  =  new  SurrealDbOptionsBuilder ( ) . FromConnectionString ( connectionString ) . Build ( ) ; 
283+             } ) ; 
265284    } 
266-      
285+ 
267286    /// <summary> 
268287    /// Defines the SQL script used to create the database. 
269288    /// </summary> 
@@ -347,7 +366,7 @@ public static IResourceBuilder<SurrealDbServerResource> WithDataBindMount(this I
347366
348367        return  builder . WithBindMount ( source ,  "/data" ) ; 
349368    } 
350-      
369+ 
351370    /// <summary> 
352371    /// Copies init files into a SurrealDB container resource. 
353372    /// </summary> 
@@ -367,10 +386,10 @@ public static IResourceBuilder<SurrealDbServerResource> WithInitFiles(this IReso
367386        { 
368387            throw  new  DistributedApplicationException ( $ "Unable to determine the file name for '{ source } '.") ; 
369388        } 
370-          
389+ 
371390        string  fileName  =  Path . GetFileName ( importFullPath ) ; 
372391        string  initFilePath  =  $ "{ initPath } /{ fileName } "; 
373-          
392+ 
374393        return  builder 
375394            . WithContainerFiles ( initPath ,  importFullPath ) 
376395            . WithEnvironment ( context => 
@@ -413,16 +432,16 @@ public static IResourceBuilder<T> WithSurrealist<T>(
413432            . WithHttpEndpoint ( targetPort :  8080 ,  name :  "http" ) 
414433            . WithRelationship ( builder . Resource ,  "Surrealist" ) 
415434            . ExcludeFromManifest ( ) ; 
416-          
435+ 
417436        surrealistContainerBuilder . WithContainerFiles ( 
418437            destinationPath :  "/usr/share/nginx/html" , 
419438            callback :  async  ( _ ,  cancellationToken )  => 
420439            { 
421-                 var  surrealDbServerInstances  =   
440+                 var  surrealDbServerInstances  = 
422441                    builder . ApplicationBuilder . Resources . OfType < SurrealDbServerResource > ( ) . ToList ( ) ; 
423-                 var  surrealDbNamespaceResources  =   
442+                 var  surrealDbNamespaceResources  = 
424443                    builder . ApplicationBuilder . Resources . OfType < SurrealDbNamespaceResource > ( ) . ToList ( ) ; 
425-                 var  surrealDbDatabaseResources  =   
444+                 var  surrealDbDatabaseResources  = 
426445                    builder . ApplicationBuilder . Resources . OfType < SurrealDbDatabaseResource > ( ) . ToList ( ) ; 
427446
428447                return  [ 
@@ -431,8 +450,8 @@ public static IResourceBuilder<T> WithSurrealist<T>(
431450                        Name  =  "instance.json" , 
432451                        Contents  =  await  WriteSurrealistInstanceJson ( 
433452                            surrealDbServerInstances , 
434-                             surrealDbNamespaceResources ,   
435-                             surrealDbDatabaseResources ,   
453+                             surrealDbNamespaceResources , 
454+                             surrealDbDatabaseResources , 
436455                            cancellationToken 
437456                        ) . ConfigureAwait ( false ) , 
438457                    } , 
@@ -443,7 +462,7 @@ public static IResourceBuilder<T> WithSurrealist<T>(
443462
444463        return  builder ; 
445464    } 
446-      
465+ 
447466    private  static   async  Task < string >  WriteSurrealistInstanceJson ( 
448467        IList < SurrealDbServerResource >  surrealDbServerInstances , 
449468        IList < SurrealDbNamespaceResource >  surrealDbNamespaceResources , 
@@ -522,16 +541,16 @@ CancellationToken cancellationToken
522541        writer . WriteEndArray ( ) ; 
523542
524543        writer . WriteEndObject ( ) ; 
525-          
544+ 
526545        await  writer . FlushAsync ( cancellationToken ) ; 
527-          
546+ 
528547        return  Encoding . UTF8 . GetString ( stream . ToArray ( ) ) ; 
529548    } 
530-      
549+ 
531550    private  static   async  Task  CreateNamespaceAsync ( 
532-         SurrealDbClient  surrealClient ,   
533-         SurrealDbNamespaceResource  namespaceResource ,   
534-         IServiceProvider  serviceProvider ,   
551+         SurrealDbClient  surrealClient , 
552+         SurrealDbNamespaceResource  namespaceResource , 
553+         IServiceProvider  serviceProvider , 
535554        CancellationToken  cancellationToken 
536555    ) 
537556    { 
@@ -543,7 +562,7 @@ CancellationToken cancellationToken
543562        try 
544563        { 
545564            var  response  =  await  surrealClient . RawQuery ( 
546-                 scriptAnnotation ? . Script  ??  $ "DEFINE NAMESPACE IF NOT EXISTS `{ namespaceResource . NamespaceName } `;",   
565+                 scriptAnnotation ? . Script  ??  $ "DEFINE NAMESPACE IF NOT EXISTS `{ namespaceResource . NamespaceName } `;", 
547566                cancellationToken :  cancellationToken 
548567            ) . ConfigureAwait ( false ) ; 
549568
@@ -556,11 +575,11 @@ CancellationToken cancellationToken
556575            logger . LogError ( e ,  "Failed to create namespace '{NamespaceName}'" ,  namespaceResource . NamespaceName ) ; 
557576        } 
558577    } 
559-      
578+ 
560579    private  static   async  Task  CreateDatabaseAsync ( 
561-         SurrealDbClient  surrealClient ,   
562-         SurrealDbDatabaseResource  databaseResource ,   
563-         IServiceProvider  serviceProvider ,   
580+         SurrealDbClient  surrealClient , 
581+         SurrealDbDatabaseResource  databaseResource , 
582+         IServiceProvider  serviceProvider , 
564583        CancellationToken  cancellationToken 
565584    ) 
566585    { 
@@ -572,7 +591,7 @@ CancellationToken cancellationToken
572591        try 
573592        { 
574593            var  response  =  await  surrealClient . RawQuery ( 
575-                 scriptAnnotation ? . Script  ??  $ "DEFINE DATABASE IF NOT EXISTS `{ databaseResource . DatabaseName } `;",   
594+                 scriptAnnotation ? . Script  ??  $ "DEFINE DATABASE IF NOT EXISTS `{ databaseResource . DatabaseName } `;", 
576595                cancellationToken :  cancellationToken 
577596            ) . ConfigureAwait ( false ) ; 
578597
0 commit comments