un

guest
1 / ?
back to lessons

Forma 1: Reparación de Estado. Forma 2: Informe Inútil.

Un Corazón Medido late en un reloj. No por necesidad. No por cambio. Por un temporizador.

Dos formas, una causa raíz: un trabajo programado sustituyendo por un diseño correcto.

Forma 1: Reparación de Estado

Una transición de estado falla para completarse de manera atómica. En lugar de arreglar la transición, un trabajo de fondo se ejecuta con un retraso y se reconcilia. Los usuarios ven estado roto durante la ventana de reconciliación.

Ejemplo de GitHub (2026-04-08): Se hizo privado el repositorio de origen de una solicitud de extracción. GitHub intentó una transición de estado: cerrar la PR, actualizar el estado del branch, borrar el estado de fusión. La transición no se completó de manera atómica. El estado de la PR mostró 'branch-forced-closed' y 'El estado de fusión no se puede cargar' simultáneamente. Un trabajo de Sidekiq de fondo se ejecutó minutos después y completó la reconciliación. Los observadores vieron estado roto durante la duración de la ventana.

El Corazón Medido: el trabajo de Sidekiq se ejecutó según el reloj. No se ejecutó porque GitHub detectó estado roto; se ejecutó porque sonó el temporizador. Un usuario que observaba la PR en tiempo real vio una PR que se contradecía a sí misma hasta la siguiente ejecución del trabajo.

Forma 2: Informe Inútil

Un informe o agregación vuelve a calcular desde cero en un intervalo fijo. Sin comprobación de caché. Sin guardia de idempotencia. Sin actualización incremental. Cada ejecución: un escaneo completo.

Ejemplos: un trabajo cron nocturno que vuelve a calcular el importe total de compras de cada usuario al escanear todas las órdenes desde el principio del tiempo. Un trabajo de análisis diario que regenera una consola de información a partir de registros de eventos brutos. Un correo semanal de resumen que consulta todas las filas en la tabla de actividad.

Cada uno se ejecuta ya sea que haya habido cambios en los datos desde la última ejecución. Cada uno escanea la historia completa incluso cuando solo los últimos 24 horas contienen nuevos datos. Cada uno sustituye la repetición programada por un diseño incremental.

La Causa Raíz Compartida

Un Corazón Medido no puede decir la verdad sobre su propio estado. Sólo sabe del reloj. Forma 1: el trabajo de reparación de estado se ejecuta a las T+5 minutos independientemente de si el estado está roto en T+0. Forma 2: el trabajo de informe se ejecuta a las 2 AM independientemente de si hubo cambios en los datos desde ayer.

El reloj no lleva información sobre lo que necesita hacerse. Un evento lleva esa información: 'una transición de estado acaba de fallar', 'nuevas órdenes acaban de llegar'. Un Corazón Medido tira esa información a la basura y la sustituye por un horario.

Drenaje de Capital

Un Corazón Medido drena capital vivo: ingenieros en espera para incidentes de estado roto. Erode la confianza social: los usuarios ven datos inconsistentes y reportan defectos que resuelven automáticamente. Amplifica otros MOADs: un trabajo de reparación de estado que escanea todos los registros para encontrar estado roto a menudo contiene MOAD-0001 (escaneo O(N²)). Un trabajo de informe que recalculariza los datos fríos puede desencadenar MOAD-0005 (estampida de caché). MOAD-0009 complica otros defectos.

La Raíz Compartida

Forma 1 y Forma 2 parecen diferentes en la superficie: una arregla el estado, la otra recalculariza los datos. La causa raíz los conecta.

Forma 1 y Forma 2 comparten una causa raíz. Désela en una oración. Luego proporcione un ejemplo de cada forma de un software que haya utilizado.

Incendio en Cambio, No en Reloj

Diseño basado en eventos dispara cuando algo cambia. El cambio de estado es el evento. El evento es el disparador.

Forma 1: la transición atómica reemplaza el trabajo de reparación.

Si una transición de estado puede dejar al sistema en un estado roto intermedio, el defecto vive en la transición, no en su ausencia de trabajo de reparación. Arregle la transición para completar de manera atómica (o transaccional). Cuando la transición se completa de manera atómica, el estado roto nunca existe. El trabajo de reparación no tiene nada que arreglar.

# DEFECT: transición no atómica deja un estado roto
def close_pr_on_repo_private(pr_id):
    pr = PR.get(pr_id)
    pr.status = 'branch-forced-closed'   # paso 1: estado parcial
    pr.save()                             # visible para los usuarios AHORA
    # ... otros pasos pueden fallar ...
    pr.merge_status = 'not_applicable'
    pr.save()                             # paso 2: ahora consistente
    # Trabajo Sidekiq de reconciliación si falla el paso 2
# SOLUCIÓN: transición atómica; ningún estado intermedio visible
def close_pr_on_repo_private(pr_id):
    with db.transaction():
        pr = PR.get(pr_id)
        pr.status = 'branch-forced-closed'
        pr.merge_status = 'not_applicable'
        pr.save()   # ambos campos se comiten atómicamente; nunca escrito a la mitad

Forma 2: la actualización incremental reemplaza el cálculo completo.

Un informe que vuelve a calcular desde cero dispara porque los datos antiguos + nuevos datos = nuevo resultado. Pero los datos antiguos + delta = mismo nuevo resultado, calculado incrementalmente. El evento: nuevos datos llegaron. El desencadenante: actualice el agregado solo para los nuevos datos.

# DEFECTO: cálculo completo programado
def nightly_totals_job():
    for user in all_users():
        total = sum(o.amount for o in user.orders)  # escaneo de todos los tiempos
        user.total_purchases = total
        user.save()

# SOLUCIÓN: actualización basada en eventos incremental
def on_order_placed(order):
    order.user.total_purchases += order.amount   # solo delta
    order.user.save()

La actualización incremental dispara cuando llega una orden, no a las 2 AM. Actualiza solo al usuario afectado. Lee solo la nueva orden, no todas las órdenes de todos los tiempos. El trabajo nocturno desaparece.

Por qué la Forma 1 Revela una Transición Rota

Un Medidor de Corazón de Forma 1 Medido revela que una transición de estado se dejó incompleta. El trabajo de reparación existe porque un ingeniero notó un estado roto y agregó un mecanismo de reconciliación en lugar de arreglar la transición. El trabajo de reparación: una solución de parche sobre una decisión arquitectónica rota.

MOAD-0009 como Amplificador

MOAD-0009 amplifica a otros MOADs. Un trabajo de reparación de estado que escanea todos los registros para encontrar el estado roto: MOAD-0001 (escaneo O(N) o O(N²) por ejecución de trabajo). Un trabajo de informe que vuelve a calcular todo frío: MOAD-0005 (estampida de caché cuando el trabajo comienza y golpea una fuente caliente). MOAD-0009 no lastima solo; entrega a otros MOADs con un horario.

Diagnóstico y Rediseño

Un equipo ejecuta un trabajo cron nocturno a las 2 AM. El trabajo escanea todos los pedidos de todos los usuarios y vuelve a computar el monto total de compras de cada usuario desde cero. El trabajo tarda 4 horas. A las 6 AM, el tablero muestra totales frescos. Entre las 2 AM y las 6 AM, el tablero muestra los totales de ayer.

¿Cuál forma de MOAD-0009 es esta? ¿Qué evento debería desencadenar el cálculo en lugar de eso? ¿Qué estructura de datos intermedia hace que la actualización sea incremental?