요청 다섯 번에 한 번이 끊기는 연결에서 업로드를 100번 실행했습니다. 실패한 업로드가 23건에서 1건으로 줄었습니다.
남은 1건은 서버가 거부한 파일이라 재시도로는 해결되지 않습니다.
이제 업로드 속도가 헤더의 파일 이름 옆에 표시되고, 큐가 비면 숨겨집니다.
시작했습니다. 볼 만한 결과가 나오면 여기에 올리겠습니다.
재현해서 원인을 찾았습니다. 수정은 리뷰할 준비가 됐습니다.
업로드 큐에 지수 백오프를 추가했습니다. 실패한 청크는 최대 다섯 번 재시도하고, 진행률 표시줄에 시도 횟수가 나옵니다. 테스트는 타임아웃과 503 경우를 다룹니다.
예전에는 실패한 청크를 그냥 버렸습니다. 이제 큐가 백오프 정책에 지연 시간을 묻고 재시도를 예약하므로, 모든 재시도가 한곳을 거칩니다.
다섯 번 실패하면 청크는 최종 실패로 처리되고 업로드는 명확한 오류와 함께 멈춥니다. 끊긴 연결에서 재시도가 끝없이 이어지지 않습니다.
큐 변경은 src/upload/queue.ts에 있고, 대기 시간은 src/upload/backoff.ts에 있습니다.
큐가 각 청크의 상태를 디스크에 씁니다. 지금 재시작 경로를 연결하고 있습니다.
시작할 때 큐가 저장된 상태를 읽고 끝나지 않은 청크만 보내므로 2GB 파일도 처음부터 다시 시작하지 않습니다.
전략에 시장에 나가라고 되어 있어서 그 함수를 추가했습니다.
1export async function goToMarket() {2await ship();3await tellDenis();4}
테스트 1개가 통과합니다. 시장의 답변은 아직 없습니다.
워처가 쓰기 전에 테스트가 파일을 읽고 있었습니다. 이제 flush 이벤트를 기다리고, 200번 연속 통과합니다.
1test('reads the synced file', async () => {2await writeFile(path, 'hello');3await watcher.flushed(path);4const text = await readFile(path);5expect(text).toBe('hello');6});
대기는 테스트 헬퍼에 있어서 다른 동기화 테스트도 함께 고쳐집니다.
새 페이지는 준비됐습니다. 탭을 없애기 전에 설정 마이그레이션을 실행해야 합니다.
| 이전 탭 | 새 섹션 |
|---|---|
| 일반 | 워크스페이스 |
| 모양 | 워크스페이스 |
| 계정 | 프로필 |
마이그레이션이 설정 212개를 오류 없이 처리했고 이전 탭은 사라졌습니다. 모든 설정이 한 페이지에 있습니다.
여기서 멈춥니다. 마이그레이션을 실행할 때까지 이전 탭은 그대로 둡니다.
두 가지를 찾았습니다. 세션 쿠키에 만료가 없고, 로그인 후 리다이렉트가 아무 URL이나 받습니다. 나머지는 괜찮습니다.
완료했습니다. 선택한 수정은 각각 테스트와 함께 반영했고, 미룬 항목은 풀 리퀘스트에 댓글로 남겼습니다.
알겠습니다. 아무것도 바꾸지 않았고 발견 사항은 풀 리퀘스트 댓글로 남겨 둡니다.
깨끗한 환경에서 새 명령을 실행해 봤고 잘 작동합니다.
1bun add -g uploader2uploader --help
이전 curl 명령도 여전히 작동하므로 대안으로 남겨 둘 수 있습니다.
완료했습니다. 새 명령은 요청한 위치에 있고 이전 명령은 대안으로 남겼습니다.
대부분의 시간은 검색마다 모든 파일을 읽는 데 쓰입니다. 인덱스로 줄일 수 있고 작은 저장소는 거의 달라지지 않습니다.
인덱스는 파일이 바뀔 때 갱신되므로 전체를 다시 만들 필요가 없습니다.
트리는 이제 디스크 캐시에서 불러오고 백그라운드에서 갱신합니다. 달라지는 것은 대기 시간뿐입니다.
- 캐시 적중
- 94%
- 디스크 크기
- 2.1 MB
- 트리 로드 시간
- 40 ms
브랜치가 바뀌면 캐시는 저절로 비워집니다.
찾았습니다. 빈 파일은 null이 되고 코드가 바로 거기서 필드를 읽습니다.
1export function loadConfig(path: string) {2const text = readFileSync(path, 'utf8');3if (text.trim() === '') return defaults;4return { ...defaults, ...parse(text) };5}
이제 빈 파일은 기본 설정으로 처리되고 깨진 파일은 명확한 오류를 보여 줍니다.
새 이슈는 5개입니다. 3개는 실제 버그이고 그중 하나는 다음 릴리스까지 기다려도 됩니다.
| 이슈 | 종류 |
|---|---|
| Upload stalls at 99% on Safari | bug |
| Crash on a file named final_final_v2_🦆.mov | bug |
| Progress bar jumps back after resume | bug |
| Drag a folder into the upload list | feature |
| Is there a size limit? Asking for a 400 GB log file | question |
모두 라벨을 달고 중복 이슈는 이전 보고에 연결했습니다.
uploader에서 무엇을 작업할까요?
실패한 업로드 재시도
업로드 큐에 지수 백오프를 추가했습니다. 실패한 청크는 최대 다섯 번 재시도하고, 진행률 표시줄에 시도 횟수가 나옵니다. 테스트는 타임아웃과 503 경우를 다룹니다.
예전에는 실패한 청크를 그냥 버렸습니다. 이제 큐가 백오프 정책에 지연 시간을 묻고 재시도를 예약하므로, 모든 재시도가 한곳을 거칩니다.
const result = await sendChunk(chunk); if (!result.ok) return fail(chunk); if (!result.ok) { const delay = backoff.next(chunk.attempt); if (delay === null) return fail(chunk); return schedule(chunk, delay); } progress.advance(chunk.size); const DELAYS = [500, 1000, 2000, 4000, 8000]; export const backoff = { next(attempt: number) { return DELAYS[attempt] ?? null; } }; 1import { backoff } from './backoff';2import { sendChunk } from './client';3import { progress } from './progress';4import type { Chunk, UploadResult } from './types';56// TODO: remove before launch (added in 2023)7const MAX_PARALLEL = 4;8const queue: Chunk[] = [];9let running = 0;1011export function enqueue(chunks: Chunk[]) {12queue.push(...chunks);13void drain();14}1516async function drain() {17while (running < MAX_PARALLEL && queue.length > 0) {18const chunk = queue.shift();19if (!chunk) return;20running += 1;21await upload(chunk);22running -= 1;23}24}2526export async function upload(chunk: Chunk): Promise<UploadResult> {27const result = await sendChunk(chunk);28if (!result.ok) {29const delay = backoff.next(chunk.attempt);30if (delay === null) return fail(chunk);31return schedule(chunk, delay);32}33progress.advance(chunk.size);34return done(chunk);35}3637function schedule(chunk: Chunk, delay: number) {38chunk.attempt += 1;39progress.retrying(chunk);40setTimeout(() => enqueue([chunk]), delay);41}
내 머신에서 돌아갑니다. 어디서든 접속하세요.
데스크톱 앱은 내 컴퓨터에서 에이전트를 실행하고 내 서버에도 연결합니다. 휴대폰은 QR 코드로 한 번 페어링하면 Private Relay를 통해 서버에 접속합니다. 종단 간 암호화되며 포트를 열 필요가 없습니다.
uploader에서 무엇을 작업할까요?
uploader에서 무엇을 작업할까요?
uploader에서 무엇을 작업할까요?
세션을 찾을 수 없습니다.
const result = await sendChunk(chunk); if (!result.ok) { const delay = backoff.next(chunk.attempt); if (delay === null) return fail(chunk); return schedule(chunk, delay); }
const DELAYS = [500, 1000, 2000, 4000, 8000]; export const backoff = { next(attempt: number) { return DELAYS[attempt] ?? null; } };
test('retries a chunk after a 503', async () => { server.respondWith(503); await upload(chunk); clock.tick(500); expect(server.calls).toBe(2); });
하나의 작업, 여러 모델.
같은 프롬프트를 여러 모델에 한 번에 보내세요. 각 실행은 자체 워크트리와 브랜치를 가질 수 있습니다. 가장 마음에 드는 결과를 남기거나 답변을 하나로 fusion하세요.
큰 diff를 워크스루로 읽으세요.
워크스루는 큰 diff를 이해하기 쉬운 순서로 다시 놓고, 단계마다 한 문장으로 설명하며, 핵심 변경을 표시해 무엇부터 읽을지 알려 줍니다.
티켓과 도구를 클릭 한 번으로.
GitHub 이슈, 풀 리퀘스트, Linear 티켓에서 세션을 시작하면 에이전트가 스레드 전체를 받습니다. 통합 카탈로그에는 Figma와 Sentry를 포함해 160개가 넘는 서비스가 있고, 모두 클릭 한 번으로 설치됩니다.
목표나 일정을 맡기세요.
목표를 정하면 에이전트는 별도의 확인이 완료됐거나 막혔다고 판단할 때까지 턴마다 계속 작업합니다. 예약 작업은 매일 아침이든 다음 주 화요일 한 번이든 알아서 세션을 시작합니다.
쓰는 사람들의 말.
부탁한 적 없는 글들입니다.
I've had a deep experience with openchamber. I think my choice was right. This thing is really useful, smooth and silky. Go try it out quick, I strongly recommend it, no more messing around blindly.
@realchendahuang Was looking for a way to run agents from my phone, remotely on my server, other than tmux. Found OpenChamber. It is INSANELY good, highly recommended.
@NihilSineTheo Seriously, I've spent almost the whole week trying to find a tool that made sense to orchestrate agents and, as a dev (actually, a devops), openchamber is the only one that felt natural and logical.
@1un4rPunk I just want to say the app itself is phenomenal. The level of polish is just unreal. I saw OpenChamber back when it was a small project, I think maybe a couple months ago, and now it is unrecognizable. Truly amazing work. The latest release with its streaming feature is everything I could have possibly asked for and more. It is gorgeous and smooth.
이미 가진 머신에 설치하세요.
macOS, Windows, Linux에서는 데스크톱 앱, 서버에서는 명령 하나. 그다음엔 어디서든 열면 됩니다.
OpenChamber는 작업에 관한 어떤 정보도 수집하지 않습니다. 코드는 MIT 라이선스라 누구나 확인할 수 있습니다.
활동
대기 시간을 설정으로 뺄 수 있나요? 모바일에서는 더 길게 하고 싶을 수 있어요.
좋은 생각입니다. 대기 시간이 이제 배열 하나라서 후속 PR로 할 수 있습니다.