(
&mut self,
id: ReplicaId,
mut config: ReplicaConfig,
epoch: Option<u64>,
)
| 1211 | /// Add a new instance replica, by ID. |
| 1212 | #[mz_ore::instrument(level = "debug")] |
| 1213 | pub fn add_replica( |
| 1214 | &mut self, |
| 1215 | id: ReplicaId, |
| 1216 | mut config: ReplicaConfig, |
| 1217 | epoch: Option<u64>, |
| 1218 | ) -> Result<(), ReplicaExists> { |
| 1219 | if self.replica_exists(id) { |
| 1220 | return Err(ReplicaExists(id)); |
| 1221 | } |
| 1222 | |
| 1223 | config.logging.index_logs = self.log_sources.clone(); |
| 1224 | |
| 1225 | let epoch = epoch.unwrap_or(1); |
| 1226 | let metrics = self.metrics.for_replica(id); |
| 1227 | let client = ReplicaClient::spawn( |
| 1228 | id, |
| 1229 | self.build_info, |
| 1230 | config.clone(), |
| 1231 | epoch, |
| 1232 | metrics.clone(), |
| 1233 | Arc::clone(&self.dyncfg), |
| 1234 | self.replica_tx.clone(), |
| 1235 | ); |
| 1236 | |
| 1237 | // Take this opportunity to clean up the history we should present. |
| 1238 | self.history.reduce(); |
| 1239 | |
| 1240 | // Advance the uppers of source imports |
| 1241 | self.history.update_source_uppers(&self.storage_collections); |
| 1242 | |
| 1243 | // Replay the commands at the client, creating new dataflow identifiers. |
| 1244 | for command in self.history.iter() { |
| 1245 | // Skip `CreateDataflow` commands targeted at different replicas. |
| 1246 | if let Some(target_replica) = self.target_replica(command) |
| 1247 | && target_replica != id |
| 1248 | { |
| 1249 | continue; |
| 1250 | } |
| 1251 | |
| 1252 | // Re-apply this replica's dyncfg override to replayed config commands, and rebuild the |
| 1253 | // create-instance snapshot from the current dyncfg. |
| 1254 | let command = Self::specialize_command_for_replica( |
| 1255 | command.clone(), |
| 1256 | id, |
| 1257 | &self.replica_dyncfg_overrides, |
| 1258 | &self.dyncfg, |
| 1259 | ); |
| 1260 | if client.send(command).is_err() { |
| 1261 | // We swallow the error here. On the next send, we will fail again, and |
| 1262 | // restart the connection as well as this rehydration. |
| 1263 | tracing::warn!("Replica {:?} connection terminated during hydration", id); |
| 1264 | break; |
| 1265 | } |
| 1266 | } |
| 1267 | |
| 1268 | // Add replica to tracked state. |
| 1269 | if self.add_replica_state(id, client, config, epoch).is_err() { |
| 1270 | // A storage read hold issuer hung up, which only happens during process shutdown. |
no test coverage detected