블로그로 돌아가기

beads v1.0.0 지원을 출시했다. 롤백 1회, flock 버그 1건, 핫픽스 6회가 필요했다.

beads v1.0.0 지원을 출시했다. 롤백 1회, flock 버그 1건, 핫픽스 6회가 필요했다.

4월 2일, beads가 v1.0.0을 출시했다. 핵심 기능은 embedded Dolt: 데이터베이스를 인프로세스로 실행하는 제로 설정 백엔드, 별도의 서버 관리 불필요. 솔로 개발자에게는 bd init만 하면 끝이라는 약속이었다. 포트 없이, 데몬 없이, 설정 없이.

즉시 Beadbox에서 지원을 추가하기 시작했다. 핫픽스 6회, 공개 롤백 1회, bd 소스 코드 깊이 파고들기를 거쳐, 아마 몇 달 전에 만들었어야 할 레질리언스 레이어를 가지고 반대편으로 나왔다.

모든 게 망가지기 전 아침

하루는 깨끗하게 시작됐다. 코드베이스 전체에서 데드 코드 헌팅을 진행했고, 5,350줄을 제거하고 콜드 런치를 2초 개선한 v0.20.0을 출시했다. 42개의 beads 종료. 좋은 아침이었다.

그때 bd를 0.63.3으로 업그레이드했다. beads v1.0.0의 embedded Dolt 백엔드 위에 구축된 첫 릴리스였다.

Beadbox가 데이터베이스를 찾지 못했다. Embedded 모드는 .beads/dolt/ 대신 .beads/embeddeddolt/에 데이터를 저장한다. 데이터베이스 이름도 바뀌었다. 하드코딩된 beads에서 metadata.json에서 읽는 프로젝트 접두사로. 그리고 WebSocket 서버가 DOLT_HASHOF_TABLE을 통한 O(1) 변경 감지에 사용하던 bd sql은 embedded 모드에서 전혀 지원되지 않았다.

처음 10분 만에 세 가지 가정이 무너졌다.

하루에 6번 릴리스

발견, 수정, 출시, 다시 발견.

v0.20.1은 OS 키체인을 사용한 자격 증명 영속성을 추가했고(이미 진행 중이던 6개의 beads 작업), 커스텀 상태 필터 버그를 수정하고 Windows 관련 문제를 패치했다.

v0.20.2는 Beadbox에 metadata.json에서 dolt_database를 읽도록 가르쳐 이름이 바뀐 데이터베이스를 찾을 수 있게 했다.

v0.20.3은 embedded 모드 가드를 추가했다. 모든 bd sql 호출을 체크로 감쌌다: embedded 모드라면 직접 SQL 쿼리 대신 CLI 기반 폴링으로 폴백한다. getDoltDir 함수는 먼저 embeddeddolt/을 확인하는 법을 배웠다.

v0.20.4는 embedded 레이아웃을 위한 --db 경로 정규화를 수정했다. 이전 디렉터리 구조에서 작동하던 경로가 새 구조에서는 깨졌다.

각 수정이 다음 문제를 드러냈다.

Flock

v0.20.4 이후, 안정됐다고 생각했다. 그래서 간단한 동시성 테스트를 실행했다: bd list 5번 동시 호출.

4개가 실패했다.

Embedded Dolt는 모든 커맨드의 전체 수명 동안 데이터베이스에 대한 배타적 파일 잠금(flock)을 획득한다. PersistentPreRun부터 PersistentPostRun까지, 다른 아무것도 접근할 수 없다. 이것은 설계대로다. 이것 없이는 동시 엔진 초기화가 nil-pointer panic을 일으킨다(beads#2571). Flock은 크래시를 방지한다. 하지만 embedded 모드에서 bd가 사실상 단일 프로세스라는 의미이기도 하다.

Beadbox는 단일 프로세스가 아니다. WebSocket 서버는 매초 변경 사항을 폴링한다. UI는 페이지 로드 시 여러 server action을 실행한다. 백그라운드 폴러가 실행되는 동안 앱을 클릭하는 사용자는 동시 bd 호출을 생성한다. Flock은 첫 번째를 제외한 모든 것을 차단한다.

DoltHub 블로그 포스트는 embedded 구현의 의도된 동작을 설명했다: 동시 호출자는 "지수 백오프로 자연스럽게 대기열에 쌓여야" 한다. 하지만 arch가 출시된 소스 코드를 검토한 결과, bd가 TryLockLOCK_NB(논블로킹)로 사용하는 것을 발견했다. 기다리지 않는다. 즉시 실패한다. 잠금 레이어가 두 개다: 위에 bd의 flock, 아래에 Dolt의 드라이버 수준 백오프. 첫 번째 레이어가 두 번째를 쇼트서킷한다. 재시도 로직은 코드베이스에 존재하지만, flock이 Dolt의 백오프가 실행될 기회를 얻기 전에 연결을 거부하기 때문에 실행되지 않는다.

수정(FlockSharedNonBlock을 통한 읽기 작업용 공유 잠금)은 bd의 소스에 존재한다. 아직 연결되지 않았을 뿐이다.

이것이 Beadbox가 해결하는 문제입니다.

전체 에이전트 플릿이 무엇을 하고 있는지 실시간으로 파악하세요.

베타 기간 중 무료로 사용해 보세요 →

롤백했다

움직이는 표적에 핫픽스를 계속 릴리스하거나, 물러나서 적절한 레질리언스 레이어를 구축하거나. 물러났다.

모든 v0.20.x 릴리스가 공개 리포에서 제거됐다. v0.19.0이 권장 버전으로 복귀했다. 무슨 일이 있었고 무엇을 해야 하는지 설명하는 디스커션을 게시하고, beadbox.app에 배너를 추가했다. 결정부터 완료까지 30분.

깨진 릴리스가 공개된 매 시간은 누군가가 다운로드하고, flock 문제에 부딪히고, 제품을 탓하는 시간이다. 다른 사람의 나쁜 첫 경험을 디버깅하는 것보다 롤백을 설명하는 게 낫다.

우리만 그런 게 아니었다

디버깅하는 동안, beads 사용자 Kevin이 beads#2938을 게시했다: "Beads feels painful to use." 그는 정확히 우리가 겪고 있던 embedded-to-server 혼란을 포함한 문제를 디버깅하는 데 9.5시간을 보냈다. v1.0.0으로의 업그레이드가 조용히 그의 워크스페이스를 서버 모드에서 embedded 모드로 전환했고(beads#2949), 기존 issue들을 빈 새 데이터베이스 뒤에 숨겨버렸다.

9.5시간. 숙련된 사용자, 초보가 아니다. beads를 잘 아는 사람의 경험이 이렇다면 문제는 사용자가 아니다. 마이그레이션 경로다.

v0.21.0에서 구축한 것

개별 실패를 패치하는 대신, 잠금 경합을 정상적인 운영 조건으로 취급하는 레이어를 구축했다.

지수 백오프를 사용한 flock 재시도. 모든 bd CLI 호출은 최대 5회 재시도한다. 시도 간격은 100ms에서 1.6초. lib/bd.ts 한 곳에 위치하므로 모든 커맨드가 무료로 얻는다. 일반적인 경우를 커버한다: 두 호출이 충돌하고, 하나가 잠시 기다리고, 둘 다 성공한다.

그레이스풀 디그레이데이션 UI. 잠금 경합이 더 이상 에러 화면을 의미하지 않는다. 앱은 새로고침 인디케이터와 함께 오래된 데이터를 표시한다. 경합이 30초 이상 지속되면 호박색 배너가 상황을 설명한다. 잠금이 해제되면 배너가 사라지고 데이터가 자동으로 새로고침된다.

오토 프로모트 제안. 반복적인 경합이 서버 모드로의 마이그레이션을 제안하는 트리거가 된다: 백업, --server로 재초기화, 복원. 원클릭. Beadbox를 다른 bd 소비자와 함께 실행하는 모든 사람에게 올바른 답이며, 이제 앱이 직접 알려준다.

Embedded 모드 감지. getDoltDirembeddeddolt/를 확인하고 적절히 라우팅한다. bd sql 호출은 가드된다. WebSocket 파이프라인은 embedded 모드에서 CLI 기반 폴링으로 폴백한다(느리지만 단일 프로세스 제약을 존중한다).

배운 것

Embedded Dolt는 설계상 단일 프로세스다. 버그가 아니다. Flock은 실제 panic을 방지한다. beads 워크스페이스를 동시에 소비하는 모든 도구는 접근을 직렬화하거나 서버 모드로 실행해야 한다. Beadbox에게는 서버 모드가 올바른 기본값이다. Embedded는 재시도 레이어가 간헐적 충돌을 흡수하는 가벼운 사용에서 작동한다.

문서는 의도를 설명했지, 구현을 설명하지 않았다. DoltHub 블로그는 백오프라고 했다. 코드는 TryLockLOCK_NB라고 했다. 문서가 그렇게 말했기 때문에 동시 읽기가 작동해야 한다고 가정하며 시간을 보냈다. 소스를 읽으니 혼란이 몇 분 만에 해결됐다. 동작이 문서와 일치하지 않으면 코드를 읽어라.

출시 전에 동시성을 테스트하라. v0.20.4가 공개될 때까지 동시 bd 호출을 실행하지 않았다. for i in {1..5}; do bd list & done; wait로 어떤 릴리스보다 먼저 flock 문제를 잡을 수 있었다. 5초의 테스트로 롤백을 피할 수 있었을 것이다.

일찍 롤백하라. 계속 앞으로 나아가려는 본능은 강하다. 가까이 있고, 수정이 보이고, 한 번만 더 릴리스. 하지만 공개된 채로 남는 깨진 릴리스는 쉽게 되돌릴 수 없는 신뢰 인출이다. v0.19.0으로 돌아간 것이 공황 상태의 점진적 릴리스 대신 레질리언스 레이어를 제대로 구축할 여유를 주었다.

환경 변수를 확인하라. BEADS_DIR가 bd를 잘못된 워크스페이스로 가리키고 있어서 시간을 허비했다. bd는 Beadbox가 모니터링하는 것과 다른 데이터베이스를 발견했고, 증상은 데이터 손상처럼 보였다. bd 커맨드가 예상치 못한 결과를 반환하면, 다른 무엇보다 먼저 env | grep BEADS를 실행하라.

현재 상황

v0.21.0이 beads v1.0.0 지원, 레질리언스 레이어, OS 키체인을 통한 자격 증명 영속성과 함께 출시됐다. 릴리스 디스커션에 전체 세부 사항이 있다.

beads v1.0.0 embedded 모드에서 간헐적 실패가 발생한다면, v0.21.0의 재시도 레이어가 처리할 수 있을 것이다. Beadbox를 같은 워크스페이스에 접근하는 다른 도구와 함께 실행 중이라면 서버 모드로 전환하라. 오토 프로모트 플로우가 원클릭으로 처리한다.

그리고 Steve나 beads 팀에서 이것을 읽고 있다면: 읽기용 공유 flock이 근본 원인을 업스트림에서 수정할 것이다. beads#2939(Unix domain sockets)는 로컬 연결도 더 깔끔하게 만들 것이다. 무엇이 릴리스되든 그 주변에서 계속 구축해 나갈 것이다.

직접 사용해 보세요

먼저 beads를 협업 레이어로 시작하세요. 시각적 관리가 필요할 때 Beadbox를 추가하세요.

베타 기간 중 무료. 계정 불필요. Dolt 네이티브 지원.

Share