Zurück zum Blog

Wir haben beads v1.0.0 Support ausgeliefert. Es brauchte einen Rollback, einen Flock-Bug und 6 Hotfixes.

Wir haben beads v1.0.0 Support ausgeliefert. Es brauchte einen Rollback, einen Flock-Bug und 6 Hotfixes.

Am 2. April veröffentlichte beads v1.0.0. Das Hauptfeature war embedded Dolt: ein Zero-Config-Backend, das die Datenbank im Prozess ausführt, kein separater Server nötig. Für Solo-Entwickler war das das Versprechen von bd init und fertig. Keine Ports, keine Daemons, keine Konfiguration.

Wir haben sofort begonnen, die Unterstützung in Beadbox einzubauen. Sechs Hotfix-Releases, ein öffentlicher Rollback und ein Deep Dive in bd's Quellcode später kamen wir auf der anderen Seite mit einer Resilienz-Schicht heraus, die wir wahrscheinlich schon Monate vorher hätten bauen sollen.

Der Morgen, bevor alles kaputt ging

Der Tag begann sauber. Wir hatten eine Dead-Code-Jagd durch die Codebase geführt und v0.20.0 mit 5.350 entfernten Zeilen und einer 2-Sekunden-Verbesserung beim Kaltstart ausgeliefert. Zweiundvierzig Beads geschlossen. Ein guter Morgen.

Dann haben wir bd auf 0.63.3 aktualisiert, das erste Release basierend auf beads v1.0.0's embedded Dolt Backend.

Beadbox konnte die Datenbank nicht finden. Der Embedded-Modus speichert Daten in .beads/embeddeddolt/ statt .beads/dolt/. Der Datenbankname änderte sich ebenfalls, von hartcodiertem beads zu einem Projektpräfix aus metadata.json. Und bd sql, das unser WebSocket-Server für O(1)-Änderungserkennung via DOLT_HASHOF_TABLE nutzte, wird im Embedded-Modus überhaupt nicht unterstützt.

Drei Annahmen innerhalb der ersten zehn Minuten gebrochen.

Sechs Releases an einem Tag

Entdecken, fixen, ausliefern, wieder entdecken.

v0.20.1 fügte Credential-Persistenz über den OS-Keychain hinzu (sechs Beads an Arbeit bereits in Bearbeitung), behob einen Custom-Status-Filter-Bug und patchte Windows-spezifische Probleme.

v0.20.2 brachte Beadbox bei, dolt_database aus metadata.json zu lesen, damit es die umbenannte Datenbank finden konnte.

v0.20.3 fügte Embedded-Modus-Guards hinzu. Jeder bd sql-Aufruf wurde mit einer Prüfung umwickelt: Falls wir im Embedded-Modus sind, auf CLI-basiertes Polling statt direkter SQL-Abfragen zurückfallen. Die getDoltDir-Funktion lernte, zuerst in embeddeddolt/ nachzuschauen.

v0.20.4 behob die --db-Pfadnormalisierung für das Embedded-Layout. Pfade, die mit der alten Verzeichnisstruktur funktionierten, brachen mit der neuen.

Jeder Fix legte das nächste Problem offen.

Der Flock

Nach v0.20.4 dachten wir, wir wären stabil. Dann haben wir einen einfachen Concurrency-Test durchgeführt: fünf bd list-Aufrufe gleichzeitig.

Vier davon schlugen fehl.

Embedded Dolt erwirbt ein exklusives File-Lock (flock) auf die Datenbank für die gesamte Lebensdauer jedes Befehls. Von PersistentPreRun bis PersistentPostRun kann nichts anderes darauf zugreifen. Das ist so beabsichtigt. Ohne das Lock verursacht die gleichzeitige Engine-Initialisierung einen nil-pointer Panic (beads#2571). Der Flock verhindert den Crash. Aber er bedeutet auch, dass bd im Embedded-Modus effektiv Single-Process ist.

Beadbox ist nicht Single-Process. Unser WebSocket-Server pollt jede Sekunde nach Änderungen. Die UI feuert beim Laden der Seite mehrere Server Actions. Ein Benutzer, der durch die App klickt, während der Hintergrund-Poller läuft, erzeugt parallele bd-Aufrufe. Der Flock blockiert alle außer dem ersten.

Der DoltHub-Blogpost über die Embedded-Implementierung beschrieb das beabsichtigte Verhalten: Gleichzeitige Aufrufer sollten sich "natürlich mit exponentiellem Backoff einreihen." Aber arch überprüfte den ausgelieferten Quellcode und stellte fest, dass bd TryLock mit LOCK_NB (nicht-blockierend) verwendet. Es wartet nicht. Es schlägt sofort fehl. Es gibt zwei Lock-Schichten: bd's Flock oben und Dolt's Backoff auf Treiberebene darunter. Die erste Schicht kurzschließt die zweite. Die Retry-Logik existiert in der Codebase, wird aber nie ausgeführt, weil der Flock die Verbindung ablehnt, bevor Dolt's Backoff eine Chance bekommt zu laufen.

Der Fix (shared Locks für Leseoperationen via FlockSharedNonBlock) existiert in bd's Quellcode. Er ist nur noch nicht verdrahtet.

Das ist das Problem, das Beadbox loest.

Echtzeit-Ueberblick ueber alles, was Ihre Agent-Flotte gerade tut.

Kostenlos testen waehrend der Beta →

Wir haben zurückgerollt

Wir konnten weiter Hotfixes gegen ein bewegliches Ziel liefern, oder zurückziehen und eine ordentliche Resilienz-Schicht bauen. Wir zogen zurück.

Alle v0.20.x-Releases wurden aus dem öffentlichen Repo entfernt. v0.19.0 kam als empfohlene Version zurück. Wir veröffentlichten eine Diskussion, die erklärte, was passiert war und was zu tun ist, und fügten einen Banner auf beadbox.app hinzu. Dreißig Minuten von der Entscheidung bis zur Umsetzung.

Jede Stunde, die ein kaputtes Release öffentlich bleibt, ist eine Stunde, in der jemand es herunterlädt, auf das Flock-Problem stößt und dem Produkt die Schuld gibt. Wir erklären lieber einen Rollback, als jemand anderem bei der Fehlersuche einer schlechten ersten Erfahrung zu helfen.

Wir waren nicht die Einzigen

Während wir debuggten, postete ein beads-Nutzer namens Kevin beads#2938: "Beads feels painful to use." Er hatte 9,5 Stunden mit dem Debuggen von Problemen verbracht, die genau die Embedded-zu-Server-Verwirrung beinhalteten, die wir auch hatten. Das Upgrade auf v1.0.0 hatte seinen Workspace stillschweigend vom Server-Modus in den Embedded-Modus umgeschaltet (beads#2949) und seine bestehenden Issues hinter einer frischen leeren Datenbank versteckt.

9,5 Stunden. Ein erfahrener Nutzer, kein Neuling. Wenn das die Erfahrung für jemanden ist, der beads gut kennt, liegt das Problem nicht beim Nutzer. Es liegt am Migrationspfad.

Was wir für v0.21.0 gebaut haben

Statt einzelne Fehler zu umgehen, haben wir eine Schicht gebaut, die Lock-Contention als normalen Betriebszustand behandelt.

Flock-Retry mit exponentiellem Backoff. Jeder bd-CLI-Aufruf versucht bis zu 5 Mal, 100ms bis 1,6 Sekunden zwischen den Versuchen. Lebt an einer Stelle in lib/bd.ts, sodass jeder Befehl es kostenlos bekommt. Das deckt den häufigen Fall ab: Zwei Aufrufe kollidieren, einer wartet kurz, beide gelingen.

Graceful-Degradation-UI. Lock-Contention bedeutet nicht mehr einen Fehlerbildschirm. Die App zeigt veraltete Daten mit einem Aktualisierungsindikator. Wenn die Contention länger als 30 Sekunden anhält, erklärt ein bernsteinfarbener Banner die Situation. Wenn das Lock frei wird, verschwindet der Banner und die Daten werden automatisch aktualisiert.

Auto-Promote-Vorschlag. Wiederholte Contention löst einen Vorschlag aus, zum Server-Modus zu migrieren: Backup, Neuinitialisierung mit --server, Wiederherstellung. Ein Klick. Das ist die richtige Antwort für jeden, der Beadbox neben anderen bd-Konsumenten betreibt, und jetzt sagt die App das, statt einen es selbst herausfinden zu lassen.

Embedded-Modus-Erkennung. getDoltDir prüft auf embeddeddolt/ und leitet entsprechend weiter. bd sql-Aufrufe sind geschützt. Die WebSocket-Pipeline fällt im Embedded-Modus auf CLI-basiertes Polling zurück (langsamer, aber respektiert die Single-Process-Einschränkung).

Was wir gelernt haben

Embedded Dolt ist designbedingt Single-Process. Kein Bug. Der Flock verhindert echte Panics. Jedes Tool, das einen beads-Workspace gleichzeitig nutzt, muss den Zugriff serialisieren oder im Server-Modus laufen. Für Beadbox ist der Server-Modus der richtige Standard. Embedded funktioniert für leichte Nutzung, wobei die Retry-Schicht gelegentliche Kollisionen absorbiert.

Die Docs beschrieben die Absicht, nicht die Implementierung. Der DoltHub-Blog sprach von Backoff. Der Code sagte TryLock mit LOCK_NB. Wir haben Zeit damit verbracht anzunehmen, dass gleichzeitige Lesevorgänge funktionieren sollten, weil die Dokumentation das sagte. Das Lesen des Quellcodes löste die Verwirrung in Minuten. Wenn Verhalten nicht zur Doku passt, lies den Code.

Teste Concurrency, bevor du auslieferst. Wir haben keine gleichzeitigen bd-Aufrufe durchgeführt, bis v0.20.4 öffentlich war. for i in {1..5}; do bd list & done; wait hätte das Flock-Problem vor jedem Release entdeckt. Fünf Sekunden Testen hätten uns einen Rollback erspart.

Rolle früh zurück. Der Instinkt, weiter vorwärts zu pushen, ist stark. Du bist nah dran, du siehst den Fix, noch ein Release. Aber jedes kaputte Release, das öffentlich bleibt, ist ein Vertrauensentzug, den du nicht leicht rückgängig machen kannst. Der Rückzug auf v0.19.0 gab uns Raum, die Resilienz-Schicht ordentlich zu bauen, statt sie in panischen Schritten auszuliefern.

Prüfe deine Umgebungsvariablen. Wir haben Stunden verloren, weil BEADS_DIR bd auf den falschen Workspace zeigte. bd entdeckte eine andere Datenbank als die, die Beadbox überwachte, und die Symptome sahen aus wie Datenkorruption. Wenn deine bd-Befehle unerwartete Ergebnisse liefern, env | grep BEADS vor allem anderen.

Aktueller Stand

v0.21.0 ist draußen mit beads v1.0.0 Support, der Resilienz-Schicht und Credential-Persistenz über den OS-Keychain. Die Release-Diskussion hat die vollständigen Details.

Wenn du beads v1.0.0 mit Embedded-Modus nutzt und intermittierende Fehler hast, sollte v0.21.0's Retry-Schicht damit umgehen können. Wenn du Beadbox neben anderen Tools betreibst, die denselben Workspace nutzen, wechsle zum Server-Modus. Der Auto-Promote-Flow macht es zu einem Klick.

Und wenn du Steve bist oder jemand im beads-Team, der das hier liest: Shared Flocks für Lesevorgänge würden die Ursache upstream beheben. beads#2939 (Unix Domain Sockets) würde lokale Verbindungen ebenfalls sauberer machen. Wir bauen weiter um das herum, was ausgeliefert wird.

Selbst ausprobieren

Starten Sie mit beads als Koordinationsschicht. Fügen Sie Beadbox hinzu, wenn Sie visuelle Übersicht brauchen.

Kostenlos während der Beta. Kein Konto erforderlich. Native Dolt-Unterstützung.

Share