La tarjeta de revisión del vault que nunca rotaba
Greenhouse tiene una tarjeta diaria “Rescatar o Guardar” del vault para lo más antiguo que hay en el vault. Rescatar tiene sentido, saca el elemento de ahí. Guardar se supone que es la otra respuesta válida: dejarlo en paz, ya lo revisé, pregúntame de nuevo más tarde. Excepto que ese “más tarde” nunca llegó. Encontré el bug mientras trabajaba en un issue adyacente, y es un buen ejemplo de un comentario que me mintió durante semanas antes de que alguien lo detectara.
La lógica de selección es determinista a propósito: ordena todos los elementos guardados en el vault por cuánto tiempo llevan inactivos, y la revisión diaria muestra el que lleva más tiempo inactivo. Ese es un diseño razonable. El problema era qué hacía “Guardar” con esa selección. Había un comentario justo al lado explicando que hacer clic en Guardar descarta la tarjeta y la selección “cambia naturalmente (mañana).” Leí ese comentario, le creí, y pasé al siguiente issue. Estaba mal. Guardar no escribía nada en la base de datos. Fijaba un dato de estado en el componente de Svelte y lo daba por hecho. La tarjeta desaparecía por el resto de esa sesión porque un id del lado del cliente quedaba marcado como descartado, pero la consulta subyacente nunca cambiaba. Recargar la app, o volver al día siguiente, y el mismo elemento exacto volvía a ganar el concurso de “más inactivo.” Para siempre. Cada otro elemento del vault simplemente… nunca se revisaba.
La solución terminó siendo una sola columna nula. Agregué last_reviewed_at a la tabla de elementos, separada de vaulted_at. Esa separación importó más de lo esperado al escribirla: vaulted_at es sobre lo que se construye el orden de inactividad, así que si Guardar hubiera tocado esa columna en cambio, habría reiniciado el reloj de inactividad del elemento y empezado a corromper el orden exacto del que depende la revisión, la misma trampa que el diseño original de Guardar esquivó al no volver a llamar al comando de vault. Dos preguntas distintas, dos columnas distintas: “cuánto tiempo lleva esto en el vault” y “cuándo fue la última vez que lo revisé y decidí dejarlo.”
Con la nueva columna en su lugar, la selección diaria obtuvo un filtro más: saltar cualquier cosa revisada dentro de la cadencia configurada, y luego tomar la más antigua de lo que queda. Guardar ahora hace una llamada real al backend, y la bandera de descarte del lado del cliente en la que había estado confiando simplemente desaparece por completo, comentario incluido.
La parte que sigo pensando es que este bug era invisible en todo sentido obvio. Sin crash, sin error, sin prueba fallida. La tarjeta se comportaba exactamente como decía el comentario, dentro de una sola sesión. Solo se notaría algo raro usando la app a lo largo de varios días y preguntándose por qué la revisión del vault seguía mostrando la misma idea de canción inactiva de hace tres semanas. Que es justo cómo se reportó en primer lugar.
Lección que me llevo de esto: un comentario que explica por qué el comportamiento actual está bien es una afirmación, no un hecho, y necesita el mismo escepticismo que el código mismo. “Cambia naturalmente mañana” suena como una declaración sobre el sistema. En realidad era una declaración sobre la intención de alguien para el sistema que nunca se construyó.
Lecturas relacionadas
Bandeja de semillas: las ideas que desaparecieron durante una semana
En Greenhouse, una idea capturada desaparecía durante toda una semana. La solución: una zona con cuenta regresiva, sin botón para saltarse la espera.
Estante de cosecha: darle a los elementos publicados de Greenhouse un lugar donde caer
Publicar un proyecto era de solo escritura: la base de datos estampaba un timestamp, una rama de la insignia nunca podía renderizar, y toda la recompensa del pipeline era invisible.
La base de datos vacía que parecía perfectamente sana
SQLite trata un archivo de cero bytes como una base de datos válida, así que toda verificación de corrupción pasaba, y la poda de respaldos habría borrado las copias buenas en una semana.
También te podría ser útil
Proton Mail
Correo electrónico cifrado de extremo a extremo, con arquitectura de acceso cero.
Como socio de Proton, obtengo ingresos por las compras que califican de los servicios de privacidad y seguridad de Proton (Pass, Mail, VPN, Drive).
Más informaciónProton Pass
Gestor de contraseñas centrado en la privacidad, del equipo detrás de Proton Mail.
Como socio de Proton, obtengo ingresos por las compras que califican de los servicios de privacidad y seguridad de Proton (Pass, Mail, VPN, Drive).
Más informacióneSIM Airalo
eSIM de datos local para viajes - sin necesidad de cambiar una SIM física.
Este es mi enlace de referido de Airalo. Obtienes un descuento en tu primer eSIM y yo obtengo crédito de Airalo para el mío.
Más información