Diseño de movimiento por lotes que gestiona fallos parciales
Cómo estructurar una operación de cambio masivo de registros para que el usuario conozca el resultado de cada elemento y pueda recuperarse de errores

Una aplicación de gestión de colecciones permite mover varios ítems a la vez, por ejemplo 40 ediciones de películas de la estantería "Sala de estar" a "Caja de mudanza 03". Si la petición se agota sin respuesta, el usuario queda sin saber si la operación se completó, falló o quedó parcialmente ejecutada. El artículo propone un diseño de API y UI que haga visible el estado de cada registro.
Definir claramente qué se mueve
El movimiento solo altera la ubicación registrada del catálogo; no implica la posición física del disco. Por eso se mantiene la distinción entre "ubicación registrada" y "ubicación física" cuando el producto lo soporta. La selección debe basarse en IDs de edición estables, no en títulos, para evitar ambigüedades con múltiples copias del mismo film. Al enviarse la solicitud, se congelan los IDs y el destino en un registro de operación, evitando reconstruir la lista a partir de filtros que podrían haber cambiado.
Delimitar la frontera transaccional
Si el sistema de almacenamiento permite una transacción atómica y el negocio requiere que todos los registros se muevan juntos, esa sería la solución más sencilla. Sin embargo, el diseño asume que los ítems pueden actualizarse de forma independiente y que el lote puede abarcar varias peticiones. El contrato debe quedar claro antes de la sumisión: cada edición se procesa por separado y el resultado puede incluir ítems exitosos y fallidos.
Diferenciar lo desconocido de lo fallido
Se asigna un ID durable a la operación, que el cliente usa para consultar el estado tras una recarga o interrupción de red. Los estados sugeridos son: pendiente, procesando, exitoso, conflicto y fallido. En la UI, "resultado no confirmado" indica falta de información, no un error definitivo. Un resumen tipo "32 movidos, 3 requieren revisión, 5 pendientes" brinda más contexto que un simple porcentaje.
Retries seguros a nivel de ítem
Un timeout puede ocurrir después de que el servidor haya aplicado el cambio pero antes de que el cliente reciba la respuesta. Siguiendo la guía de patrones de reintento de Azure, cada acción de ítem lleva una identidad compuesta por el ID de operación y el ID de edición. La respuesta se persiste de forma atómica; una petición repetida con la misma identidad devuelve el resultado ya registrado, evitando efectos duplicados. La identidad está vinculada al contenido original de la solicitud y se rechaza su reutilización con un destino distinto.
Tratar los conflictos como decisiones
Si otro dispositivo mueve la edición a "Estantería del dormitorio" mientras el lote está en curso, el servidor compara la versión actual con la esperada. Un desajuste genera un conflicto, no una sobrescritura silenciosa. La UI muestra la ubicación origen esperada, la actual y el destino solicitado, y permite al usuario conservar la ubicación actual o iniciar un nuevo movimiento basado en el estado más reciente.
Soporte de deshacer (undo)
Se guarda la ubicación original de cada ítem exitoso. Una solicitud de deshacer intenta restaurar esa ubicación, pero solo si el registro sigue reflejando el movimiento a revertir; de lo contrario se presenta un conflicto. Los resultados del undo se reportan con la misma claridad por ítem que la operación original.
Revisar casos incómodos
Se analizan escenarios como pérdida de respuesta tras escritura exitosa, recarga durante el procesamiento, reenvío de solicitud, eliminación del destino antes de la ejecución, borrado de una edición a mitad del lote y deshacer después de una edición posterior. En cada caso se plantea qué conoce el servidor, qué puede mostrar la interfaz de forma veraz y qué acciones quedan disponibles.
Aunque el ejemplo usa un catálogo de DVD, el enfoque se aplica a cualquier operación masiva de etiquetas, carpetas de documentos o asignaciones de activos. Un lote confiable deja un registro legible de lo ocurrido, y ese registro es la base para que el usuario recupere su estado sin adivinar.

