gabriel / musehub public
fix BREAKING fix/phase8-blob-put-30s #1 / 1
AI Agent gabriel · 40 days ago · May 11, 2026 · Diff

fix: resolve 30s blob PUT in wire_push_stream phase 8

Root cause: Python 3.14's http.client incorrectly parses the HTTP exchange when botocore uses Expect: 100-continue and MinIO sends 100 Continue + 200 OK in the same TCP segment. The 200 OK bytes appear as unparsed_data after the 100 Continue headers, triggering MissingHeaderBodySeparatorDefect in urllib3. urllib3 catches the defect but pools the connection without draining the response body (dirty connection). Phase 8's next PUT reuses this dirty connection; MinIO reads the leftover bytes as a new request, becomes confused, and closes the connection after its 30s keep-alive timeout.

Fix: register a before-send.s3.PutObject event handler in BlobBackend._get_client() that removes the Expect header before each PUT. Without Expect: 100-continue, botocore sends headers and body in a single shot. MinIO responds with a plain 200 OK that Python 3.14's http.client parses cleanly. No dirty connection.

Also adds Config(request_checksum_calculation='when_required', response_checksum_validation='when_required') to suppress optional CRC32 headers that add response overhead.

Tests added: tests/test_phase8_atomic.py T1-T9 TDD regression suite tests/test_diag_phase8.py event-loop alive + timing diagnostics tests/bench_phase8_repro.py minimal INSERT step benchmark tests/bench_phases.py layered push pipeline benchmark

Result: phase 8 blob_put drops from 30.266s to 0.005s.

sha256:345db3b22e487edaa82b2b4056956ef2f74267db2bf059d9e7974e994e1d094e sha
sha256:9f7057b00b18c78e7317744e9d397ab050693d6904c7d41c2890383f8042b989 snapshot
← Older Oldest on fix/phase8-blob-put-30s
All commits
Newer → Latest on fix/phase8-blob-put-30s

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:345db3b22e487edaa82b2b4056956ef2f74267db2bf059d9e7974e994e1d094e --body "your comment"