Skip to content

Conversation

@DanielleMaywood
Copy link
Contributor

@DanielleMaywood DanielleMaywood commented Dec 17, 2025

Closes #435

Problem

When compression was enabled, Conn.Write sent messages across many small frames due to the flate library's internal bufferFlushSize (240 bytes). Each flush triggered a writeFrame call, producing alternating ~236 and 4 byte frames. This broke clients like Unreal Engine that only process one frame per tick.

Solution

Conn.Write now compresses the entire message into a buffer first, then transmits it as a single frame. Messages below flateThreshold bypass compression and are sent uncompressed in a single frame.

For CompressionContextTakeover mode, the flateWriter destination is restored after buffered compression to ensure subsequent Writer() streaming calls work correctly.


🤖 PR was written by Claude Code using Opus 4.5 then reviewed by Opus 4.5 and a human 👩‍🚀

Closes #435

### Problem

When compression was enabled, `Conn.Write` sent messages across many small frames due to the flate library's internal `bufferFlushSize` (240 bytes). Each flush triggered a `writeFrame` call, producing alternating ~236 and 4 byte frames. This broke clients like Unreal Engine that only process one frame per tick.

### Solution

`Conn.Write` now compresses the entire message into a buffer first, then transmits it as a single frame. Messages below `flateThreshold` bypass compression and are sent uncompressed in a single frame.

For `CompressionContextTakeover` mode, the flateWriter destination is restored after buffered compression to ensure subsequent `Writer()` streaming calls work correctly.

### Changes

- **write.go**: Buffer compressed output before transmission
- **compress_test.go**: Added regression tests for single-frame behavior and Write/Writer interop
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a critical bug where compressed WebSocket messages were sent across many small frames instead of a single frame, breaking clients like Unreal Engine that process only one frame per tick. The fix buffers the entire compressed message before transmission.

  • Modifies Conn.Write to compress messages into a temporary buffer first, then transmit as a single frame
  • Adds logic to send small messages (below threshold) uncompressed in a single frame
  • Restores flateWriter destination after buffered compression to maintain compatibility with subsequent Writer() streaming calls

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
write.go Implements single-frame compression by buffering compressed data before transmission; adds flateWriter destination restoration for context takeover mode
compress_test.go Adds regression tests verifying single-frame transmission for both compression modes and tests Write/Writer API interoperability

The implementation is well-designed and handles the key edge cases correctly:

  1. Mutex handling: The mutex is properly locked once at the start and unlocked via defer in all code paths
  2. Buffer management: Uses the buffer pool pattern consistently with proper cleanup via defer
  3. Context takeover: Correctly restores the flateWriter destination to ensure subsequent Writer() calls work
  4. Error handling: All error paths return properly wrapped errors
  5. Test coverage: The tests cover both compression modes, threshold boundaries, and the critical Write→Writer sequence

The code follows the existing conventions in the codebase and the logic is sound. No issues were identified that require changes.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Transmit only single frame in Write when compression enabled too

1 participant