Ensure the Data Plane has the array open before dispatching Put/Delete. Looks up the catalog entry for `array_id.name`, then dispatches `OpenArray` to the Data Plane. This is idempotent on the Data Plane side: if the array is already open with the same schema hash, the handler returns `Ok`. Returns an error if the catalog entry is missing (the array was never registered on this node) or if the `
(
state: &Arc<SharedState>,
array_id: &nodedb_array::types::ArrayId,
vshard: crate::types::VShardId,
tenant_id: crate::types::TenantId,
)
| 231 | /// Returns an error if the catalog entry is missing (the array was never |
| 232 | /// registered on this node) or if the `OpenArray` dispatch fails. |
| 233 | async fn ensure_array_open( |
| 234 | state: &Arc<SharedState>, |
| 235 | array_id: &nodedb_array::types::ArrayId, |
| 236 | vshard: crate::types::VShardId, |
| 237 | tenant_id: crate::types::TenantId, |
| 238 | ) -> crate::Result<()> { |
| 239 | let (schema_msgpack, schema_hash, prefix_bits) = { |
| 240 | let cat = state |
| 241 | .array_catalog |
| 242 | .read() |
| 243 | .unwrap_or_else(|p| p.into_inner()); |
| 244 | match cat.lookup_by_name(&array_id.name) { |
| 245 | Some(entry) => ( |
| 246 | entry.schema_msgpack.clone(), |
| 247 | entry.schema_hash, |
| 248 | entry.prefix_bits, |
| 249 | ), |
| 250 | None => { |
| 251 | return Err(crate::Error::Internal { |
| 252 | detail: format!( |
| 253 | "ensure_array_open: array '{}' not in catalog — register it before applying ops", |
| 254 | array_id.name |
| 255 | ), |
| 256 | }); |
| 257 | } |
| 258 | } |
| 259 | }; |
| 260 | |
| 261 | let open_request_id = state.next_request_id(); |
| 262 | let open_plan = crate::bridge::envelope::PhysicalPlan::Array( |
| 263 | nodedb_physical::physical_plan::ArrayOp::OpenArray { |
| 264 | array_id: array_id.clone(), |
| 265 | schema_msgpack, |
| 266 | schema_hash, |
| 267 | prefix_bits, |
| 268 | }, |
| 269 | ); |
| 270 | let open_request = Request { |
| 271 | request_id: open_request_id, |
| 272 | tenant_id, |
| 273 | database_id: DatabaseId::DEFAULT, |
| 274 | vshard_id: vshard, |
| 275 | plan: open_plan, |
| 276 | deadline: std::time::Instant::now() + Duration::from_secs(30), |
| 277 | priority: Priority::Normal, |
| 278 | trace_id: TraceId::generate(), |
| 279 | consistency: ReadConsistency::Strong, |
| 280 | idempotency_key: None, |
| 281 | event_source: crate::event::EventSource::CrdtSync, |
| 282 | user_roles: Vec::new(), |
| 283 | user_id: None, |
| 284 | statement_digest: None, |
| 285 | }; |
| 286 | |
| 287 | let mut open_rx = state.tracker.register(open_request_id); |
| 288 | |
| 289 | let dispatch_result = match state.dispatcher.lock() { |
| 290 | Ok(mut d) => d.dispatch(open_request), |
no test coverage detected