Migration Guide¶
v1.8.0 → v1.8.1¶
No breaking changes — wire-compatible with v1.8.0.
v1.8.1 is a maintenance release focusing on bug fixes, type cleanup, and documentation.
Changes¶
Server.senderandClient.senderare now properties :get_sender()is deprecated and will be removed in a future version. Useserver.senderandclient.senderinstead.BaseSocketrefactored fromProtocoltoABC: stronger inheritance guarantees. No user-facing changes required.PendingRequestRule.can_handlenow truthful : no longer requires explicittry_handle()dispatch.- Handshake encode/decode exceptions no longer swallowed : JSON errors now propagate.
SO_REUSEADDRmoved tobind()only : client sockets no longer inherit the option.handshake_timeoutpropagated to client socket instances : config was previously ignored on the client side.- AsyncSocket selector loop fixed : no more busy-loop after self-disconnect.
- Test suite ~7× faster (49s → 7s) via
pytest-xdist. - 30 new unit tests, 100% coverage on
Writer. - Compatibility table updated — both
1.8.0and1.8.1are registered.
Action required¶
- Migrate from
get_sender()to.sender(deprecation warning, not a failure).
# Before (v1.8.0)
server.get_sender().send(request, client=client.conn)
# After (v1.8.1)
server.sender.send(request, client=client.conn)
v1.7.5 → v1.8.0¶
Breaking change : handshake protocol — NOT backward compatible.
v1.8.0 replaces the old HELLO/HELLO_ACK message-based handshake with a JSON raw-socket
protocol. Handshake now exchanges JSON payloads ({"v": "1.8.0", "meta": {}}) directly
over the TCP stream before any Veltix framing.
Action required¶
- All clients and servers must be upgraded together — mixed-version handshakes will fail (v1.7.x sends a binary Veltix frame as HELLO, v1.8.0 expects a JSON payload).
- No source-level API changes needed —
client.connect()still returnsbool, the handshake is still automatic and transparent. HELLO/HELLO_ACKare no longer available as imports (they were never meant for public use).
What changed¶
- Handshake is now synchronous:
connect()blocks until the JSON handshake completes or the socket timeout fires. The internal_handshake_doneEvent has been removed. HelloRuleremoved — the handshake no longer routes through the message dispatch pipeline. This is an internal change only.ERROR/INVALID_REQUESTsystem types (codes 20, 21) were kept and re-exported in v1.8.0 (since removed in v2.0.0b3).- Compatibility table now includes
Version(1, 8, 0)andVersion(1, 8, 1).
# Before (v1.7.5) — HELLO/HELLO_ACK over Veltix wire protocol
# After (v1.8.0) — JSON over raw TCP, then normal Veltix protocol
# No code changes required.
v1.7.1 → v1.7.2¶
No breaking changes — wire-compatible with v1.7.0/v1.7.1.
v1.7.2 is a stability release with 10 bug fixes, +108 tests, and documentation polish. No protocol changes.
Action required¶
None — drop-in upgrade.
v1.7.0 → v1.7.1¶
No breaking changes — wire-compatible with v1.7.0.
v1.7.1 is a stability release with 6 bug fixes and no protocol changes.
Changes¶
- Fixed:
AsyncSocketselector idempotency on_close_server_client - Fixed:
ClientInfo._idwith__eq__/__hash__for stable identity - Fixed: daemon threads no longer block process exit
- Fixed:
close_client()type hint corrected toOptional[int] - Fixed:
send_and_waittimeout compatibility with Python < 3.11 - Fixed: HELLO_ACK version validation in
_check_server_handshake - New public exports:
NetworkError,TimeoutError
Action required¶
None — drop-in upgrade.
v1.6.10 → v1.7.0¶
Breaking change : wire format — NOT backward compatible.
v1.7.0 adds 2 MAGIC bytes (b"VX") at the start of every frame. The header size
increases from 14 to 16 bytes. v1.7.0 cannot communicate with earlier versions.
Before (v1.6.10) : [2B size][2B code][4B CRC][4B request_id][ content ]
After (v1.7.0) : [2B MAGIC][2B size][2B code][4B CRC][4B request_id][content ]
^^^^^^^^
new — always 0x56 0x58 ("VX")
Action required¶
- All clients and servers must be upgraded together — mixed-version communication
will fail with
RequestError("Invalid magic bytes"). - No source-level API changes needed — the wire format change is transparent to
application code using
Request/Responseobjects.
New features¶
AsyncSocket: selectors-based backend — switch viaSocketCore.ASYNC. Up to 2x stress throughput (76 929 msg/s vs 37 676 msg/s).- Protocol hardening : MAGIC bytes, auto-resynchronization on corruption,
MAX_BUFFER_SIZE(20 MB) for DoS protection. - Benchmark
--socket-core: test threading, async, or both side-by-side. - Benchmark
--runs N: average results over multiple runs.
See CHANGELOG.md for the full list of changes.
v1.6.9 → v1.6.10¶
Breaking changes in public API :
PerformanceMode removed¶
PerformanceMode enum and ServerConfig.performance_mode / ClientConfig.performance_mode no longer exist. The socket
timeout is now hardcoded. If you were setting a performance mode, remove that configuration.
# Before (v1.6.9)
from veltix import PerformanceMode
config = ServerConfig(host="0.0.0.0", port=8080, performance_mode=PerformanceMode.HIGH)
# After (v1.6.10) — just remove the parameter
config = ServerConfig(host="0.0.0.0", port=8080)
@server.route callback order flipped¶
Server route callbacks now receive (client, response) instead of (response, client). Client routes
(@client.route) are unaffected — they still use (response, client=None).
# Before (v1.6.9)
@server.route(CHAT)
def on_chat(response, client):
...
# After (v1.6.10)
@server.route(CHAT)
def on_chat(client, response):
...
Response.latency and Response.timestamp removed¶
The latency and timestamp fields have been removed from Response. Use client.ping_server() /
server.ping_client() for latency measurement instead.
# Before (v1.6.9)
response = client.send_and_wait(request, timeout=5.0)
print(f"{response.latency:.2f}ms")
# After (v1.6.10)
response = client.send_and_wait(request, timeout=5.0)
print(f"Got: {response.content.decode()}")
server.clients now returns list[ClientInfo]¶
The clients property on Server now returns list[ClientInfo] directly instead of internal ClientEntry objects.
Access patterns are simplified :
# Before (v1.6.9)
entry = server.clients[0]
entry.info.conn # client connection
entry.info.addr # client address
# After (v1.6.10)
client = server.clients[0]
client.conn # client connection (same)
client.addr # client address (same)
client.handshake_done # handshake status (same)
v1.6.6 → v1.6.8¶
No breaking changes to public API.
Internals refactored :
ReconnectHandlernow takes a singleClientContextProtocol instead of 8 individual callbacksRequestHandler.handle()now uses a Rules system internally :PingRule,HelloRule,PendingRequestRule,RouteRule,OnRecvRule,UnhandledRule
These are internal architecture changes only. No changes required in your application code.
v1.6.0 → v1.6.4¶
No breaking changes since v1.6.2. The socket_core module renamed from veltix.socket to veltix.socket_core does not
affect the public API : all exports go through veltix/__init__.py.
server.clients now returns list[ClientEntry]¶
If you iterate over server.clients, update access patterns:
# Before (v1.6.3 and earlier)
client = server.clients[0]
client.conn # raw socket
client.handshake_done # bool
# After (v1.6.4)
entry = server.clients[0]
entry.info.conn # client connection
entry.info.handshake_done # handshake status
entry.buffer # MessageBuffer
entry.id # client ID
Note
ClientEntry was replaced by ClientInfo in v1.6.10. See the v1.6.9→v1.6.10 section above for the current access
pattern.
v1.6.0 → v1.6.2¶
Breaking changes in protocol/API:
request_idchanged from UUID string tobytes(4 bytes) — NOTE: this was later changed toint(2 bytes) in v2.0.0- Wire format changed (header/hash/request_id), upgrade both client/server together
- Handshake version check now requires exact
major.minor.patchmatch - Minimum supported Python version is now 3.8+
Custom request id migration (v1.6.0 → v1.6.2)¶
# Before (v1.5.x)
Request(T, b"x", request_id="my-id")
# After (v1.6.2)
Request(T, b"x", request_id=b"\x01\x02\x03\x04") # bytes
# After (v2.0.0)
Request(T, b"x", request_id=42) # int
Logging/display migration (v1.6.0 → v1.6.2)¶
# Before (v1.5.x)
response.request_id[:8]
# After (v1.6.2)
response.request_id.hex()[:8]
# After (v2.0.0) — request_id is now an int, not bytes
response.request_id # just use the int directly
v1.5.0 → v1.6.0¶
No breaking changes to public API.
ClientInfonow has tag methods:add_tag(),has_tag(),has_all_tags(),has_any_tags(),get_tag(),remove_tag(),clear_tags()ServerConfig.max_connectiondefault changed from2to-1(unlimited)- New
ServerConfig/ClientConfigfield:socket_core(default:SocketCore.THREADING) veltix.utilsnow exports encoding helpers andformat_bytes- Benchmark suite now supports
--save results.json
v1.4.0 → v1.5.0¶
Breaking change: on_disconnect on the client now receives a DisconnectState argument.
# Before (v1.4.0)
client.set_callback(Events.ON_DISCONNECT, lambda: print("Disconnected"))
# After (v1.5.0)
client.set_callback(Events.ON_DISCONNECT, lambda state: print(f"Disconnected — permanent={state.permanent}"))
New optional fields in ClientConfig: retry, retry_delay, buffer_size.
New optional fields in ServerConfig: buffer_size.
v1.3.0 → v1.4.0¶
No breaking changes to public API.
on_connect(server-side) now fires after the handshake is complete —client.handshake_doneis alwaysTruewhen it fires.connect()(client-side) now blocks until the handshake is done. It is safe to send messages immediately after it returns.- New
ClientConfigfields:handshake_timeout(default:5.0),max_workers(default:4) - New
ServerConfigfields:handshake_timeout(default:5.0),max_workers(default:4)
v1.2.x → v1.3.0¶
No breaking changes to public API.