Buffer a snapshot chunk and, when complete, assemble and apply all ops.
(
&self,
msg: &ArraySnapshotChunkMsg,
)
| 73 | |
| 74 | /// Buffer a snapshot chunk and, when complete, assemble and apply all ops. |
| 75 | pub async fn handle_snapshot_chunk( |
| 76 | &self, |
| 77 | msg: &ArraySnapshotChunkMsg, |
| 78 | ) -> Result<InboundOutcome, Option<ArrayRejectMsg>> { |
| 79 | let key = (msg.array.clone(), msg.snapshot_hlc_bytes); |
| 80 | |
| 81 | let assembled: Option<(SnapshotHeader, Vec<SnapshotChunk>)> = { |
| 82 | let mut snapshots = match self.snapshots().lock() { |
| 83 | Ok(g) => g, |
| 84 | Err(_) => { |
| 85 | error!(array = %msg.array, "array_inbound: snapshot mutex poisoned (chunk)"); |
| 86 | return Err(None); |
| 87 | } |
| 88 | }; |
| 89 | let entry = snapshots |
| 90 | .entry(key.clone()) |
| 91 | .or_insert_with(SnapshotAssembly::new); |
| 92 | |
| 93 | let chunk = SnapshotChunk { |
| 94 | array: msg.array.clone(), |
| 95 | chunk_index: msg.chunk_index, |
| 96 | total_chunks: msg.total_chunks, |
| 97 | payload: msg.payload.clone(), |
| 98 | snapshot_hlc: Hlc::from_bytes(&msg.snapshot_hlc_bytes), |
| 99 | }; |
| 100 | entry.chunks.insert(msg.chunk_index, chunk); |
| 101 | |
| 102 | let total = msg.total_chunks as usize; |
| 103 | if let Some(h) = &entry.header { |
| 104 | if entry.chunks.len() == total { |
| 105 | let header = h.clone(); |
| 106 | let chunks_vec: Vec<SnapshotChunk> = entry.chunks.values().cloned().collect(); |
| 107 | Some((header, chunks_vec)) |
| 108 | } else { |
| 109 | None |
| 110 | } |
| 111 | } else { |
| 112 | None |
| 113 | } |
| 114 | }; |
| 115 | |
| 116 | let Some((header, mut chunks)) = assembled else { |
| 117 | let snapshots = match self.snapshots().lock() { |
| 118 | Ok(g) => g, |
| 119 | Err(_) => return Err(None), |
| 120 | }; |
| 121 | let received = snapshots |
| 122 | .get(&key) |
| 123 | .map(|e| e.chunks.len() as u32) |
| 124 | .unwrap_or(0); |
| 125 | return Ok(InboundOutcome::SnapshotPartial { |
| 126 | received, |
| 127 | total: msg.total_chunks, |
| 128 | }); |
| 129 | }; |
| 130 | |
| 131 | // Assemble snapshot. |
| 132 | let snapshot = match assemble_chunks(&header, &mut chunks) { |
no test coverage detected