Apply a committed `ArraySchema` entry on the local node. 1. Imports the Loro snapshot into the local `OriginSchemaRegistry`. 2. Decodes the `ArraySchema` and registers an `ArrayCatalogEntry` so the Data Plane can open the array when a subsequent `ArrayOp` arrives. This is the canonical DDL propagation path for followers: the Raft `ArraySchema` entry is the single source of truth — no out-of-band
(
state: &Arc<SharedState>,
tracker: &Arc<ProposeTracker>,
group_id: u64,
log_index: u64,
applied_key: u64,
payload: ArraySchemaPayload<'_>,
)
| 318 | /// `ArraySchema` entry is the single source of truth — no out-of-band |
| 319 | /// catalog registration is needed. |
| 320 | pub(crate) fn apply_array_schema( |
| 321 | state: &Arc<SharedState>, |
| 322 | tracker: &Arc<ProposeTracker>, |
| 323 | group_id: u64, |
| 324 | log_index: u64, |
| 325 | applied_key: u64, |
| 326 | payload: ArraySchemaPayload<'_>, |
| 327 | ) { |
| 328 | use nodedb_array::sync::hlc::Hlc; |
| 329 | use nodedb_array::types::ArrayId; |
| 330 | use nodedb_types::TenantId as NdTenantId; |
| 331 | |
| 332 | use crate::control::array_catalog::entry::ArrayCatalogEntry; |
| 333 | |
| 334 | let ArraySchemaPayload { |
| 335 | array, |
| 336 | snapshot_payload, |
| 337 | schema_hlc_bytes, |
| 338 | } = payload; |
| 339 | let remote_hlc = Hlc::from_bytes(&schema_hlc_bytes); |
| 340 | |
| 341 | // Use the replicated import path so every replica converges to the same |
| 342 | // schema_hlc (the one committed in the Raft log entry) rather than each |
| 343 | // bumping independently via their local HLC generator. |
| 344 | if let Err(e) = |
| 345 | state |
| 346 | .array_sync_schemas |
| 347 | .import_snapshot_replicated(array, snapshot_payload, remote_hlc) |
| 348 | { |
| 349 | warn!( |
| 350 | group_id, index = log_index, array = %array, error = %e, |
| 351 | "apply_array_schema: import_snapshot_replicated failed" |
| 352 | ); |
| 353 | tracker.complete( |
| 354 | group_id, |
| 355 | log_index, |
| 356 | applied_key, |
| 357 | Err(crate::Error::Internal { |
| 358 | detail: format!("schema import: {e}"), |
| 359 | }), |
| 360 | ); |
| 361 | return; |
| 362 | } |
| 363 | |
| 364 | // Decode the ArraySchema from the just-imported Loro document and register |
| 365 | // it in the array catalog so the Data Plane can open the array on this node. |
| 366 | match state.array_sync_schemas.to_array_schema(array) { |
| 367 | Some(schema) => match zerompk::to_msgpack_vec(&schema) { |
| 368 | Ok(schema_msgpack) => { |
| 369 | let array_id = ArrayId::new(NdTenantId::new(0), array); |
| 370 | let entry = ArrayCatalogEntry { |
| 371 | array_id, |
| 372 | name: array.to_string(), |
| 373 | schema_msgpack, |
| 374 | schema_hash: 0, |
| 375 | created_at_ms: 0, |
| 376 | prefix_bits: 8, |
| 377 | audit_retain_ms: None, |
no test coverage detected