Deliver one op to a single session via the multi-shard merger. The merger buffers ops from all vShards and drains them in HLC order, ensuring subscribers see a consistent stream regardless of which shard the op originated from.
(&self, session_id: &str, op: &ArrayOp, op_hlc: Hlc, _op_payload: &[u8])
| 135 | /// ensuring subscribers see a consistent stream regardless of which shard |
| 136 | /// the op originated from. |
| 137 | fn deliver_to_session(&self, session_id: &str, op: &ArrayOp, op_hlc: Hlc, _op_payload: &[u8]) { |
| 138 | let cursor = match self.cursors.get(session_id, &op.header.array) { |
| 139 | Some(c) => c, |
| 140 | None => { |
| 141 | // Session has not registered for this array yet — skip. |
| 142 | return; |
| 143 | } |
| 144 | }; |
| 145 | |
| 146 | // Check if this op has already been delivered. |
| 147 | if !cursor::should_send(op_hlc, cursor.last_pushed_hlc) { |
| 148 | debug!( |
| 149 | session = %session_id, |
| 150 | array = %op.header.array, |
| 151 | op_hlc = ?op_hlc, |
| 152 | "array_fanout: op already delivered, skipping" |
| 153 | ); |
| 154 | return; |
| 155 | } |
| 156 | |
| 157 | // Check if the subscriber cursor has fallen behind the GC boundary. |
| 158 | let snapshot_hlc = self |
| 159 | .snapshot_hlcs |
| 160 | .read() |
| 161 | .ok() |
| 162 | .and_then(|m| m.get(&op.header.array).copied()) |
| 163 | .unwrap_or(Hlc::ZERO); |
| 164 | |
| 165 | if snapshot_trigger::check_and_trigger( |
| 166 | session_id, |
| 167 | &op.header.array, |
| 168 | cursor.last_pushed_hlc, |
| 169 | snapshot_hlc, |
| 170 | &self.delivery, |
| 171 | ) { |
| 172 | // Subscriber needs catch-up — do not send op stream frames. |
| 173 | return; |
| 174 | } |
| 175 | |
| 176 | // Route through the multi-shard merger for HLC-ordered delivery. |
| 177 | let merger = self.mergers.get_or_create(session_id, &op.header.array); |
| 178 | merger.push_op(self.shard_id, op.clone(), &self.delivery); |
| 179 | |
| 180 | // Advance the cursor so subsequent ops from any shard know the |
| 181 | // current frontier. |
| 182 | cursor::mark_sent(&self.cursors, session_id, &op.header.array, op_hlc); |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | impl ArrayApplyObserver for ArrayFanout { |
no test coverage detected