Skip to content

Add control connection for multiplexed WebSocket operations#13

Merged
vaurdan merged 5 commits intomainfrom
feature/control-connection
Feb 5, 2026
Merged

Add control connection for multiplexed WebSocket operations#13
vaurdan merged 5 commits intomainfrom
feature/control-connection

Conversation

@vaurdan
Copy link
Contributor

@vaurdan vaurdan commented Feb 4, 2026

Summary

  • Adds new control.py module implementing control WebSocket protocol for multiplexed operations
  • Connection pool with 100 max connections (fail-fast when full) and auto-drain (>20 idle → drain to 10)
  • Automatic fallback to direct WebSocket mode when control endpoint is unavailable
  • Fixed asyncio task cleanup on program exit
  • Integration with Sprite.exec() method

Key Changes

  • src/sprites/control.py - Control connection implementation (662 lines)
  • src/sprites/loop.py - Event loop management for mixing sync/async code
  • src/sprites/websocket.py - WebSocket wrapper with ping/pong handling
  • src/sprites/sprite.py - Integration with exec method
  • tests/test_control.py - Unit tests for control protocol

Pool Configuration

  • Max pool size: 100 connections
  • Auto-drain threshold: 20 idle connections → drain to 10
  • LRU eviction based on last-used timestamp

Related

Part of feature/control-wss-239 work in sprite-env.

- Add ControlConnection and OpConn classes for control endpoint
- Add control_mode client option to enable control mode
- Add Sprite.use_control_mode(), get_control_connection(), close_control_connection()
- Export new types from __init__.py
- Add unit tests for control mode functionality
- Implement ControlPool with acquire/release semantics for connection reuse
- Add persistent event loop (loop.py) for sync API connection reuse
- Enable control mode by default in client
- Fix race condition: remove op_active check in start_op (pool manages it)
- Release connections back to pool after each operation
- Add proper close sequence in ControlConnection.close(): close websocket,
  call wait_closed(), then wait for read task to finish naturally
- Add close_timeout=2 to websockets.connect() for faster close handshake
- Add _cancel_all_tasks() to loop.py to cancel pending tasks before stopping
- Update stop_loop() to cancel all pending tasks before stopping the event loop

This fixes the "Task was destroyed but it is pending" warnings from the
websockets library's internal keepalive tasks.
Control mode is enabled by default for efficient connection reuse.
Updated tests to expect True when control_mode is not specified.
@vaurdan vaurdan merged commit fe76cca into main Feb 5, 2026
vaurdan added a commit that referenced this pull request Feb 6, 2026
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.

1 participant

Comments