@@ -1011,13 +1011,7 @@ impl PoolInner {
1011
1011
let result = pool
1012
1012
. configure_fdw ( coord. servers . as_ref ( ) )
1013
1013
. and_then ( |( ) | migrate_schema ( & pool. logger , & conn) )
1014
- . and_then ( |had_migrations| {
1015
- if had_migrations {
1016
- coord. propagate_schema_change ( & self . shard )
1017
- } else {
1018
- Ok ( ( ) )
1019
- }
1020
- } ) ;
1014
+ . and_then ( |count| coord. propagate ( & pool, count) ) ;
1021
1015
debug ! ( & pool. logger, "Release migration lock" ) ;
1022
1016
advisory_lock:: unlock_migration ( & conn) . unwrap_or_else ( |err| {
1023
1017
die ( & pool. logger , "failed to release migration lock" , & err) ;
@@ -1107,12 +1101,31 @@ impl PoolInner {
1107
1101
1108
1102
embed_migrations ! ( "./migrations" ) ;
1109
1103
1104
+ struct MigrationCount {
1105
+ old : usize ,
1106
+ new : usize ,
1107
+ }
1108
+
1109
+ impl MigrationCount {
1110
+ fn new ( old : usize , new : usize ) -> Self {
1111
+ Self { old, new }
1112
+ }
1113
+
1114
+ fn had_migrations ( & self ) -> bool {
1115
+ self . old != self . new
1116
+ }
1117
+
1118
+ fn is_new ( & self ) -> bool {
1119
+ self . old == 0
1120
+ }
1121
+ }
1122
+
1110
1123
/// Run all schema migrations.
1111
1124
///
1112
1125
/// When multiple `graph-node` processes start up at the same time, we ensure
1113
1126
/// that they do not run migrations in parallel by using `blocking_conn` to
1114
1127
/// serialize them. The `conn` is used to run the actual migration.
1115
- fn migrate_schema ( logger : & Logger , conn : & PgConnection ) -> Result < bool , StoreError > {
1128
+ fn migrate_schema ( logger : & Logger , conn : & PgConnection ) -> Result < MigrationCount , StoreError > {
1116
1129
// Collect migration logging output
1117
1130
let mut output = vec ! [ ] ;
1118
1131
@@ -1122,7 +1135,7 @@ fn migrate_schema(logger: &Logger, conn: &PgConnection) -> Result<bool, StoreErr
1122
1135
let result = embedded_migrations:: run_with_output ( conn, & mut output) ;
1123
1136
info ! ( logger, "Migrations finished" ) ;
1124
1137
1125
- let had_migrations = catalog:: migration_count ( conn) ? != old_count ;
1138
+ let new_count = catalog:: migration_count ( conn) ?;
1126
1139
1127
1140
// If there was any migration output, log it now
1128
1141
let msg = String :: from_utf8 ( output) . unwrap_or_else ( |_| String :: from ( "<unreadable>" ) ) ;
@@ -1136,14 +1149,15 @@ fn migrate_schema(logger: &Logger, conn: &PgConnection) -> Result<bool, StoreErr
1136
1149
debug ! ( logger, "Postgres migration output" ; "output" => msg) ;
1137
1150
}
1138
1151
}
1152
+ let count = MigrationCount :: new ( old_count, new_count) ;
1139
1153
1140
- if had_migrations {
1154
+ if count . had_migrations ( ) {
1141
1155
// Reset the query statistics since a schema change makes them not
1142
1156
// all that useful. An error here is not serious and can be ignored.
1143
1157
conn. batch_execute ( "select pg_stat_statements_reset()" ) . ok ( ) ;
1144
1158
}
1145
1159
1146
- Ok ( had_migrations )
1160
+ Ok ( count )
1147
1161
}
1148
1162
1149
1163
/// Helper to coordinate propagating schema changes from the database that
@@ -1207,18 +1221,23 @@ impl PoolCoordinator {
1207
1221
1208
1222
/// Propagate changes to the schema in `shard` to all other pools. Those
1209
1223
/// other pools will then recreate any tables that they imported from
1210
- /// `shard`
1211
- fn propagate_schema_change ( & self , shard : & Shard ) -> Result < ( ) , StoreError > {
1212
- let server = self
1213
- . servers
1214
- . iter ( )
1215
- . find ( |server| & server. shard == shard)
1216
- . ok_or_else ( || constraint_violation ! ( "unknown shard {shard}" ) ) ?;
1217
-
1218
- for pool in self . pools . lock ( ) . unwrap ( ) . values ( ) {
1219
- if let Err ( e) = pool. remap ( server) {
1220
- error ! ( pool. logger, "Failed to map imports from {}" , server. shard; "error" => e. to_string( ) ) ;
1221
- return Err ( e) ;
1224
+ /// `shard`. If `pool` is a new shard, we also map all other shards into
1225
+ /// it.
1226
+ fn propagate ( & self , pool : & PoolInner , count : MigrationCount ) -> Result < ( ) , StoreError > {
1227
+ // pool is a new shard, map all other shards into it
1228
+ if count. is_new ( ) {
1229
+ for server in self . servers . iter ( ) {
1230
+ pool. remap ( server) ?;
1231
+ }
1232
+ }
1233
+ // pool had schema changes, refresh the import from pool into all other shards
1234
+ if count. had_migrations ( ) {
1235
+ let server = self . server ( & pool. shard ) ?;
1236
+ for pool in self . pools . lock ( ) . unwrap ( ) . values ( ) {
1237
+ if let Err ( e) = pool. remap ( server) {
1238
+ error ! ( pool. logger, "Failed to map imports from {}" , server. shard; "error" => e. to_string( ) ) ;
1239
+ return Err ( e) ;
1240
+ }
1222
1241
}
1223
1242
}
1224
1243
Ok ( ( ) )
@@ -1231,4 +1250,11 @@ impl PoolCoordinator {
1231
1250
pub fn servers ( & self ) -> Arc < Vec < ForeignServer > > {
1232
1251
self . servers . clone ( )
1233
1252
}
1253
+
1254
+ fn server ( & self , shard : & Shard ) -> Result < & ForeignServer , StoreError > {
1255
+ self . servers
1256
+ . iter ( )
1257
+ . find ( |server| & server. shard == shard)
1258
+ . ok_or_else ( || constraint_violation ! ( "unknown shard {shard}" ) )
1259
+ }
1234
1260
}
0 commit comments