Build a `JoinResponse` snapshotting the current topology and routing. Used both by the happy-path return and by the idempotent re-join short-circuit. The strict cluster_id check is the same as the one at the top of `join_flow` — a catalog-attached server with no stamped cluster_id is an invariant violation and we reject the join rather than synthesise a sentinel identity.
(&self, req: &JoinRequest)
| 347 | /// invariant violation and we reject the join rather than |
| 348 | /// synthesise a sentinel identity. |
| 349 | fn build_current_response(&self, req: &JoinRequest) -> JoinResponse { |
| 350 | let cluster_id = match self.catalog.as_ref() { |
| 351 | Some(catalog) => match catalog.load_cluster_id() { |
| 352 | Ok(Some(id)) => id, |
| 353 | Ok(None) => { |
| 354 | return reject( |
| 355 | "server catalog is attached but has no cluster_id — refusing to \ |
| 356 | issue a JoinResponse without a real cluster identity" |
| 357 | .to_string(), |
| 358 | ); |
| 359 | } |
| 360 | Err(e) => { |
| 361 | return reject(format!("failed to read cluster_id from catalog: {e}")); |
| 362 | } |
| 363 | }, |
| 364 | None => self.node_id, |
| 365 | }; |
| 366 | |
| 367 | let topology_clone = self |
| 368 | .topology |
| 369 | .read() |
| 370 | .unwrap_or_else(|p| p.into_inner()) |
| 371 | .clone(); |
| 372 | let routing_clone = { |
| 373 | let mr = self.multi_raft.lock().unwrap_or_else(|p| p.into_inner()); |
| 374 | mr.routing().clone() |
| 375 | }; |
| 376 | // Re-use the pure builder from `bootstrap/handle_join.rs`. |
| 377 | // `handle_join_request` is idempotent against the same |
| 378 | // (id, addr) — at this point the topology already |
| 379 | // contains the new node, so this call only rebuilds the |
| 380 | // wire response. |
| 381 | let mut topo = topology_clone; |
| 382 | handle_join_request(req, &mut topo, &routing_clone, cluster_id) |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | /// Build a failure `JoinResponse` with the given error message. |
no test coverage detected