@@ -71,6 +71,17 @@ pub fn reconnect() -> Result<(), Error> {
7171 Ok ( ( ) )
7272}
7373
74+ /// Re-create databases from existing config,
75+ /// preserving connections.
76+ pub fn reload_from_existing ( ) {
77+ let _lock = lock ( ) ;
78+
79+ let config = config ( ) ;
80+ let databases = from_config ( & config) ;
81+
82+ replace_databases ( databases, true ) ;
83+ }
84+
7485/// Initialize the databases for the first time.
7586pub fn init ( ) {
7687 let config = config ( ) ;
@@ -180,6 +191,15 @@ impl ToUser for (&str, Option<&str>) {
180191 }
181192}
182193
194+ impl ToUser for & pgdog_config:: User {
195+ fn to_user ( & self ) -> User {
196+ User {
197+ user : self . name . clone ( ) ,
198+ database : self . database . clone ( ) ,
199+ }
200+ }
201+ }
202+
183203/// Databases.
184204#[ derive( Default , Clone ) ]
185205pub struct Databases {
@@ -354,95 +374,123 @@ pub(crate) fn new_pool(
354374 user : & crate :: config:: User ,
355375 config : & crate :: config:: Config ,
356376) -> Option < ( User , Cluster ) > {
377+ let existing_roles = databases ( )
378+ . cluster ( user)
379+ . ok ( )
380+ . map ( |cluster| cluster. redetect_roles ( ) ) ;
381+
357382 let sharded_tables = config. sharded_tables ( ) ;
358383 let omnisharded_tables = config. omnisharded_tables ( ) ;
359384 let sharded_mappings = config. sharded_mappings ( ) ;
360385 let sharded_schemas = config. sharded_schemas ( ) ;
361386 let general = & config. general ;
362387 let databases = config. databases ( ) ;
363- let shards = databases. get ( & user. database ) ;
364-
365- if let Some ( shards) = shards {
366- let mut shard_configs = vec ! [ ] ;
367- for user_databases in shards {
368- let has_single_replica = user_databases. len ( ) == 1 ;
369- let primary = user_databases
370- . iter ( )
371- . find ( |d| d. role == Role :: Primary )
372- . map ( |primary| PoolConfig {
373- address : Address :: new ( primary, user) ,
374- config : Config :: new ( general, primary, user, has_single_replica) ,
375- } ) ;
376- let replicas = user_databases
377- . iter ( )
378- . filter ( |d| d. role == Role :: Replica )
379- . map ( |replica| PoolConfig {
380- address : Address :: new ( replica, user) ,
381- config : Config :: new ( general, replica, user, has_single_replica) ,
382- } )
383- . collect :: < Vec < _ > > ( ) ;
384-
385- shard_configs. push ( ClusterShardConfig { primary, replicas } ) ;
386- }
387-
388- let mut sharded_tables = sharded_tables
389- . get ( & user. database )
390- . cloned ( )
391- . unwrap_or_default ( ) ;
392- let sharded_schemas = sharded_schemas
393- . get ( & user. database )
394- . cloned ( )
395- . unwrap_or_default ( ) ;
396-
397- for sharded_table in & mut sharded_tables {
398- let mappings = sharded_mappings. get ( & (
399- sharded_table. database . clone ( ) ,
400- sharded_table. column . clone ( ) ,
401- sharded_table. name . clone ( ) ,
402- ) ) ;
403388
404- if let Some ( mappings) = mappings {
405- sharded_table. mapping = Mapping :: new ( mappings) ;
389+ let mut shards = if let Some ( shards) = databases. get ( & user. database ) . cloned ( ) {
390+ shards
391+ } else {
392+ return None ;
393+ } ;
406394
407- if let Some ( ref mapping) = sharded_table. mapping {
408- if !mapping_valid ( mapping) {
409- warn ! (
410- "sharded table name=\" {}\" , column=\" {}\" has overlapping ranges" ,
411- sharded_table. name. as_ref( ) . unwrap_or( & String :: from( "" ) ) ,
412- sharded_table. column
413- ) ;
395+ let mut shard_configs = vec ! [ ] ;
396+ for ( shard_number, user_databases) in shards. iter_mut ( ) . enumerate ( ) {
397+ let role_detector = user_databases. iter ( ) . any ( |d| d. role == Role :: Auto ) ;
398+
399+ if let Some ( ref shard_roles) = existing_roles
400+ . as_ref ( )
401+ . map ( |existing_roles| existing_roles. get ( shard_number) . cloned ( ) )
402+ . flatten ( )
403+ . flatten ( )
404+ {
405+ for user_database in user_databases. iter_mut ( ) {
406+ // Override role with automatically detected one.
407+ if let Some ( role) = shard_roles. get ( & user_database. number ) {
408+ if user_database. role == Role :: Auto {
409+ user_database. role = role. role ;
414410 }
415411 }
416412 }
417413 }
418414
419- let omnisharded_tables = omnisharded_tables
420- . get ( & user. database )
421- . cloned ( )
422- . unwrap_or ( vec ! [ ] ) ;
423- let sharded_tables = ShardedTables :: new ( sharded_tables, omnisharded_tables) ;
424- let sharded_schemas = ShardedSchemas :: new ( sharded_schemas) ;
425-
426- let cluster_config = ClusterConfig :: new (
427- general,
428- user,
429- & shard_configs,
430- sharded_tables,
431- config. multi_tenant ( ) ,
432- sharded_schemas,
433- & config. rewrite ,
434- ) ;
415+ let has_single_replica = user_databases. len ( ) == 1 ;
416+ let primary = user_databases
417+ . iter ( )
418+ . find ( |d| d. role == Role :: Primary )
419+ . map ( |primary| PoolConfig {
420+ address : Address :: new ( primary, user, primary. number ) ,
421+ config : Config :: new ( general, primary, user, has_single_replica) ,
422+ } ) ;
423+ let replicas = user_databases
424+ . iter ( )
425+ . filter ( |d| matches ! ( d. role, Role :: Replica | Role :: Auto ) )
426+ . map ( |replica| PoolConfig {
427+ address : Address :: new ( replica, user, replica. number ) ,
428+ config : Config :: new ( general, replica, user, has_single_replica) ,
429+ } )
430+ . collect :: < Vec < _ > > ( ) ;
431+
432+ shard_configs. push ( ClusterShardConfig {
433+ primary,
434+ replicas,
435+ role_detector,
436+ } ) ;
437+ }
435438
436- Some ( (
437- User {
438- user : user. name . clone ( ) ,
439- database : user. database . clone ( ) ,
440- } ,
441- Cluster :: new ( cluster_config) ,
442- ) )
443- } else {
444- None
439+ let mut sharded_tables = sharded_tables
440+ . get ( & user. database )
441+ . cloned ( )
442+ . unwrap_or_default ( ) ;
443+ let sharded_schemas = sharded_schemas
444+ . get ( & user. database )
445+ . cloned ( )
446+ . unwrap_or_default ( ) ;
447+
448+ for sharded_table in & mut sharded_tables {
449+ let mappings = sharded_mappings. get ( & (
450+ sharded_table. database . clone ( ) ,
451+ sharded_table. column . clone ( ) ,
452+ sharded_table. name . clone ( ) ,
453+ ) ) ;
454+
455+ if let Some ( mappings) = mappings {
456+ sharded_table. mapping = Mapping :: new ( mappings) ;
457+
458+ if let Some ( ref mapping) = sharded_table. mapping {
459+ if !mapping_valid ( mapping) {
460+ warn ! (
461+ "sharded table name=\" {}\" , column=\" {}\" has overlapping ranges" ,
462+ sharded_table. name. as_ref( ) . unwrap_or( & String :: from( "" ) ) ,
463+ sharded_table. column
464+ ) ;
465+ }
466+ }
467+ }
445468 }
469+
470+ let omnisharded_tables = omnisharded_tables
471+ . get ( & user. database )
472+ . cloned ( )
473+ . unwrap_or ( vec ! [ ] ) ;
474+ let sharded_tables = ShardedTables :: new ( sharded_tables, omnisharded_tables) ;
475+ let sharded_schemas = ShardedSchemas :: new ( sharded_schemas) ;
476+
477+ let cluster_config = ClusterConfig :: new (
478+ general,
479+ user,
480+ & shard_configs,
481+ sharded_tables,
482+ config. multi_tenant ( ) ,
483+ sharded_schemas,
484+ & config. rewrite ,
485+ ) ;
486+
487+ Some ( (
488+ User {
489+ user : user. name . clone ( ) ,
490+ database : user. database . clone ( ) ,
491+ } ,
492+ Cluster :: new ( cluster_config) ,
493+ ) )
446494}
447495
448496/// Load databases from config.
0 commit comments