Lanzamos soporte para beads v1.0.0. Requirió un rollback, un bug de flock y 6 hotfixes.
El 2 de abril, beads lanzó v1.0.0. La funcionalidad principal era embedded Dolt: un backend sin configuración que ejecuta la base de datos en el mismo proceso, sin servidor separado que administrar. Para desarrolladores individuales, era la promesa de bd init y listo. Sin puertos, sin daemons, sin configuración.
Empezamos a agregar soporte en Beadbox inmediatamente. Seis hotfixes, un rollback público y una inmersión profunda en el código fuente de bd después, salimos del otro lado con una capa de resiliencia que probablemente deberíamos haber construido meses antes.
La mañana antes de que todo se rompiera
El día empezó limpio. Habíamos hecho una cacería de código muerto en toda la base de código y lanzamos v0.20.0 con 5,350 líneas eliminadas y una mejora de 2 segundos en el arranque en frío. Cuarenta y dos beads cerrados. Una buena mañana.
Entonces actualizamos bd a 0.63.3, el primer release construido sobre el backend embedded Dolt de beads v1.0.0.
Beadbox no podía encontrar la base de datos. El modo embedded almacena datos en .beads/embeddeddolt/ en lugar de .beads/dolt/. El nombre de la base de datos también cambió, de beads hardcodeado a un prefijo de proyecto leído de metadata.json. Y bd sql, que nuestro servidor WebSocket usaba para detección de cambios O(1) via DOLT_HASHOF_TABLE, no está soportado en modo embedded en absoluto.
Tres suposiciones rotas en los primeros diez minutos.
Seis releases en un día
Descubrir, arreglar, lanzar, descubrir de nuevo.
v0.20.1 agregó persistencia de credenciales usando el keychain del OS (seis beads de trabajo ya en progreso), corrigió un bug del filtro de estado personalizado y parchó problemas específicos de Windows.
v0.20.2 enseñó a Beadbox a leer dolt_database de metadata.json para que pudiera encontrar la base de datos renombrada.
v0.20.3 agregó guardas para el modo embedded. Cada llamada a bd sql fue envuelta con una verificación: si estamos en modo embedded, recurrir a polling basado en CLI en lugar de consultas SQL directas. La función getDoltDir aprendió a buscar primero en embeddeddolt/.
v0.20.4 corrigió la normalización de rutas --db para el layout embedded. Las rutas que funcionaban con la estructura de directorios anterior se rompían con la nueva.
Cada fix revelaba el siguiente problema.
El flock
Después de v0.20.4, pensamos que estábamos estables. Entonces ejecutamos una prueba simple de concurrencia: cinco llamadas a bd list al mismo tiempo.
Cuatro fallaron.
Embedded Dolt adquiere un file lock exclusivo (flock) sobre la base de datos durante toda la vida de cada comando. Desde PersistentPreRun hasta PersistentPostRun, nada más puede acceder. Esto es por diseño. Sin él, la inicialización concurrente del motor causa un nil-pointer panic (beads#2571). El flock previene el crash. Pero también significa que en modo embedded, bd es efectivamente single-process.
Beadbox no es single-process. Nuestro servidor WebSocket sondea cambios cada segundo. La UI dispara múltiples server actions al cargar la página. Un usuario navegando la app mientras el poller de fondo ejecuta generará llamadas concurrentes a bd. El flock bloquea todas excepto la primera.
El post del blog de DoltHub sobre la implementación embedded describía el comportamiento esperado: los llamadores concurrentes deberían "hacer cola naturalmente con backoff exponencial." Pero arch revisó el código fuente publicado y encontró que bd usa TryLock con LOCK_NB (no-bloqueante). No espera. Falla inmediatamente. Hay dos capas de lock: el flock de bd arriba, y el backoff a nivel de driver de Dolt debajo. La primera capa cortocircuita la segunda. La lógica de reintentos existe en la base de código, pero nunca se ejecuta porque el flock rechaza la conexión antes de que el backoff de Dolt tenga oportunidad de actuar.
El fix (locks compartidos para operaciones de lectura via FlockSharedNonBlock) existe en el código fuente de bd. Simplemente no está conectado todavía.
Este es el problema que Beadbox resuelve.
Visibilidad en tiempo real de lo que toda tu flota de agentes esta haciendo.
Podíamos seguir lanzando hotfixes contra un objetivo en movimiento, o retroceder y construir una capa de resiliencia apropiada. Retrocedimos.
Todos los releases v0.20.x fueron removidos del repo público. v0.19.0 volvió como la versión recomendada. Publicamos una discusión explicando qué pasó y qué hacer, y agregamos un banner en beadbox.app. Treinta minutos desde la decisión hasta completado.
Cada hora que un release roto permanece público es una hora donde alguien lo descarga, se encuentra con el problema del flock y culpa al producto. Preferimos explicar un rollback que depurar la mala primera experiencia de alguien más.
No fuimos los únicos
Mientras depurábamos, un usuario de beads llamado Kevin publicó beads#2938: "Beads feels painful to use." Había pasado 9.5 horas depurando problemas que incluían exactamente la confusión entre embedded y servidor que nosotros estábamos enfrentando. La actualización a v1.0.0 había cambiado silenciosamente su workspace del modo servidor al modo embedded (beads#2949), ocultando sus issues existentes detrás de una base de datos nueva vacía.
9.5 horas. Un usuario experimentado, no alguien nuevo con la herramienta. Si esa es la experiencia para alguien que conoce bien beads, el problema no es el usuario. Es la ruta de migración.
Lo que construimos para v0.21.0
En lugar de parchear fallas individuales, construimos una capa que trata la contención de locks como una condición de operación normal.
Flock retry con backoff exponencial. Cada llamada al CLI de bd reintenta hasta 5 veces, 100ms a 1.6 segundos entre intentos. Vive en un solo lugar en lib/bd.ts, así que cada comando lo obtiene gratis. Esto cubre el caso común: dos llamadas colisionan, una espera brevemente, ambas tienen éxito.
UI de degradación elegante. La contención de locks ya no significa una pantalla de error. La app muestra datos obsoletos con un indicador de actualización. Si la contención persiste más de 30 segundos, un banner ámbar explica la situación. Cuando el lock se libera, el banner desaparece y los datos se refrescan automáticamente.
Sugerencia de auto-promote. La contención repetida dispara una sugerencia para migrar al modo servidor: backup, reinicializar con --server, restaurar. Un clic. Esta es la respuesta correcta para cualquiera que ejecuta Beadbox junto a otros consumidores de bd, y ahora la app te lo dice en lugar de dejarte averiguarlo solo.
Detección de modo embedded.getDoltDir verifica embeddeddolt/ y enruta en consecuencia. Las llamadas a bd sql están protegidas. El pipeline de WebSocket recurre a polling basado en CLI en modo embedded (más lento, pero respeta la restricción single-process).
Lo que aprendimos
Embedded Dolt es single-process por diseño. No es un bug. El flock previene panics reales. Cualquier herramienta que consume un workspace de beads concurrentemente necesita serializar el acceso o ejecutar en modo servidor. Para Beadbox, el modo servidor es el valor por defecto correcto. Embedded funciona para uso ligero con la capa de reintentos absorbiendo las colisiones ocasionales.
La documentación describía la intención, no la implementación. El blog de DoltHub decía backoff. El código decía TryLock con LOCK_NB. Pasamos tiempo asumiendo que las lecturas concurrentes deberían funcionar porque la documentación decía que sí. Leer el código fuente resolvió la confusión en minutos. Cuando el comportamiento no coincide con la documentación, lee el código.
Prueba la concurrencia antes de lanzar. No ejecutamos llamadas concurrentes a bd hasta que v0.20.4 era público. for i in {1..5}; do bd list & done; wait habría detectado el problema del flock antes de cualquier release. Cinco segundos de pruebas nos habrían ahorrado un rollback.
Haz rollback temprano. El instinto de seguir avanzando es fuerte. Estás cerca, puedes ver el fix, un release más. Pero cada release roto que permanece público es un retiro de confianza que no puedes deshacer fácilmente. Retroceder a v0.19.0 nos dio espacio para construir la capa de resiliencia apropiadamente en lugar de lanzarla en incrementos de pánico.
Revisa tus variables de entorno. Perdimos horas porque BEADS_DIR apuntaba bd al workspace equivocado. bd estaba descubriendo una base de datos diferente a la que Beadbox estaba monitoreando, y los síntomas parecían corrupción de datos. Si tus comandos de bd devuelven resultados inesperados, env | grep BEADS antes de cualquier otra cosa.
Estado actual
v0.21.0 está disponible con soporte para beads v1.0.0, la capa de resiliencia y persistencia de credenciales via el keychain del OS. La discusión del release tiene los detalles completos.
Si estás en beads v1.0.0 con modo embedded y experimentas fallos intermitentes, la capa de reintentos de v0.21.0 debería manejarlo. Si ejecutas Beadbox junto a otras herramientas que acceden al mismo workspace, cambia al modo servidor. El flujo de auto-promote lo hace en un clic.
Y si eres Steve o alguien del equipo de beads leyendo esto: shared flocks para lecturas arreglaría la causa raíz upstream. beads#2939 (Unix domain sockets) haría las conexiones locales más limpias también. Seguiremos construyendo alrededor de lo que se lance.
Pruébalo tú mismo
Empieza con beads como capa de coordinación. Agrega Beadbox cuando necesites supervisión visual.
Gratis durante la beta. Sin cuenta requerida. Compatible nativamente con Dolt.