Decode the Data Plane's MessagePack response into (group_key, agg_value) pairs. The response is an `rmpv::Value::Array` of `Map` rows. Each row contains the group-by columns and the aggregate value (e.g., `"avg_temperature"`).
(
payload: &[u8],
group_by: &[String],
agg_func: &str,
)
| 195 | /// The response is an `rmpv::Value::Array` of `Map` rows. Each row contains |
| 196 | /// the group-by columns and the aggregate value (e.g., `"avg_temperature"`). |
| 197 | fn decode_aggregate_response( |
| 198 | payload: &[u8], |
| 199 | group_by: &[String], |
| 200 | agg_func: &str, |
| 201 | ) -> crate::Result<Vec<(String, f64)>> { |
| 202 | if payload.is_empty() { |
| 203 | return Ok(Vec::new()); |
| 204 | } |
| 205 | |
| 206 | let value: rmpv::Value = |
| 207 | rmpv::decode::read_value(&mut &payload[..]).map_err(|e| crate::Error::Internal { |
| 208 | detail: format!("decode aggregate response: {e}"), |
| 209 | })?; |
| 210 | |
| 211 | let rows = match value { |
| 212 | rmpv::Value::Array(rows) => rows, |
| 213 | _ => return Ok(Vec::new()), |
| 214 | }; |
| 215 | |
| 216 | let mut results = Vec::with_capacity(rows.len()); |
| 217 | for row in &rows { |
| 218 | let rmpv::Value::Map(fields) = row else { |
| 219 | continue; |
| 220 | }; |
| 221 | |
| 222 | // Extract group key: concatenate group-by column values. |
| 223 | let group_key = if group_by.is_empty() { |
| 224 | "__all__".to_string() |
| 225 | } else { |
| 226 | group_by |
| 227 | .iter() |
| 228 | .filter_map(|col| { |
| 229 | fields.iter().find_map(|(k, v)| { |
| 230 | if k.as_str().is_some_and(|s| s == col) { |
| 231 | Some(v.as_str().unwrap_or("").to_string()) |
| 232 | } else { |
| 233 | None |
| 234 | } |
| 235 | }) |
| 236 | }) |
| 237 | .collect::<Vec<_>>() |
| 238 | .join("\0") |
| 239 | }; |
| 240 | |
| 241 | // Extract aggregate value by matching the agg key pattern: "{func}_{column}". |
| 242 | let agg_value = fields.iter().find_map(|(k, v)| { |
| 243 | let key_str = k.as_str()?; |
| 244 | if key_str.starts_with(agg_func) { |
| 245 | v.as_f64().or_else(|| v.as_i64().map(|i| i as f64)) |
| 246 | } else { |
| 247 | None |
| 248 | } |
| 249 | }); |
| 250 | |
| 251 | if let Some(val) = agg_value { |
| 252 | results.push((group_key, val)); |
| 253 | } |
| 254 | } |