wse-client 2.2.1 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,6 +29,9 @@ High-performance WebSocket server built in Rust with native clustering, E2E encr
29
29
  | **Compression** | zlib for client-facing messages above threshold (default 1024 bytes) |
30
30
  | **MessagePack** | Opt-in binary transport via `?format=msgpack`, roughly 2x faster serialization, 30% smaller |
31
31
  | **Message signing** | Selective HMAC-SHA256 signing for critical operations, nonce-based replay prevention |
32
+ | **Queue groups** | Round-robin dispatch within named groups for load-balanced worker pools |
33
+ | **Topic ACL** | Per-connection allow/deny glob patterns for topic access control |
34
+ | **Graceful drain** | `drain()` sends Close frame to all clients, rejects new connections, notifies cluster peers |
32
35
 
33
36
  ### End-to-End Encryption
34
37
 
@@ -55,6 +58,7 @@ High-performance WebSocket server built in Rust with native clustering, E2E encr
55
58
  | **Circuit breaker** | 10 failures to open, 60s reset, 3 half-open probe calls |
56
59
  | **Dead letter queue** | 1000-entry ring buffer for failed cluster sends |
57
60
  | **Presence sync** | PresenceUpdate/PresenceFull frames, CRDT last-write-wins conflict resolution |
61
+ | **Topology API** | `cluster_info()` returns connected peer list with address, instance_id, status |
58
62
 
59
63
  ### Presence Tracking
60
64
 
@@ -254,6 +258,7 @@ server.broadcast(topic, text) # Fan-out to topic subscribers
254
258
  ```python
255
259
  server.subscribe_connection(conn_id, ["prices", "news"]) # Subscribe to topics
256
260
  server.subscribe_connection(conn_id, ["chat"], {"status": "online"}) # Subscribe with presence data
261
+ server.subscribe_connection(conn_id, ["tasks"], queue_group="workers") # Subscribe with queue group (round-robin)
257
262
  server.unsubscribe_connection(conn_id, ["news"]) # Unsubscribe from specific topics
258
263
  server.unsubscribe_connection(conn_id, None) # Unsubscribe from all topics
259
264
  server.get_topic_subscriber_count("prices") # Subscriber count for a topic
@@ -261,6 +266,26 @@ server.get_topic_subscriber_count("prices") # Subscrib
261
266
 
262
267
  Subscriptions are cleaned up automatically on disconnect. In cluster mode, interest changes are propagated to peers via SUB/UNSUB frames.
263
268
 
269
+ **Queue groups**: connections in the same `queue_group` receive messages round-robin instead of fanout. Normal subscribers (no queue group) still receive all messages. Useful for distributing work across a pool of consumers.
270
+
271
+ ### Topic ACL
272
+
273
+ Per-connection topic access control with glob pattern matching.
274
+
275
+ ```python
276
+ # Allow only "user:*" topics, deny everything else
277
+ server.set_topic_acl(conn_id, allow=["user:*"])
278
+
279
+ # Allow "data:*" but deny "data:internal:*"
280
+ server.set_topic_acl(conn_id, allow=["data:*"], deny=["data:internal:*"])
281
+
282
+ # Must be called before subscribe_connection
283
+ server.subscribe_connection(conn_id, ["data:prices"]) # allowed
284
+ server.subscribe_connection(conn_id, ["data:internal:audit"]) # denied
285
+ ```
286
+
287
+ Deny patterns take precedence over allow patterns. Supports `*` (any characters) and `?` (single character) wildcards. Applied at subscribe time.
288
+
264
289
  ### Presence Tracking
265
290
 
266
291
  Requires `presence_enabled=True` in the constructor.
@@ -321,6 +346,7 @@ server.connect_cluster(
321
346
 
322
347
  server.cluster_connected() # True if connected to at least one peer
323
348
  server.cluster_peers_count() # Number of active peer connections
349
+ server.cluster_info() # List of connected peers (address, instance_id, connected)
324
350
  ```
325
351
 
326
352
  Nodes form a full TCP mesh automatically. The cluster protocol uses a custom binary frame format with an 8-byte header, 12 message types, and capability negotiation during handshake. Features:
@@ -368,11 +394,14 @@ health = server.health_snapshot()
368
394
  server.get_connection_count() # Lock-free AtomicUsize read
369
395
  server.get_connections() # List all connection IDs (snapshot)
370
396
  server.disconnect(conn_id) # Force-disconnect a connection
397
+ server.drain(close_code=4300, close_reason="shutting down", timeout=10) # Graceful drain
371
398
  server.inbound_queue_depth() # Events waiting to be drained
372
399
  server.inbound_dropped_count() # Events dropped due to full queue
373
400
  server.get_cluster_dlq_entries() # Retrieve failed cluster messages from dead letter queue
374
401
  ```
375
402
 
403
+ `drain()` sends a WebSocket Close frame to all connected clients and rejects new connections. The drain wait runs as a separate task, so the command processor stays responsive. Use for zero-downtime deployments and rolling restarts.
404
+
376
405
  ---
377
406
 
378
407
  ## Security
@@ -1,5 +1,5 @@
1
1
  export declare const WS_PROTOCOL_VERSION = 1;
2
- export declare const WS_CLIENT_VERSION = "2.1.1";
2
+ export declare const WS_CLIENT_VERSION = "2.3.1";
3
3
  export declare const HEARTBEAT_INTERVAL = 15000;
4
4
  export declare const IDLE_TIMEOUT = 40000;
5
5
  export declare const CONNECTION_TIMEOUT = 10000;
package/dist/constants.js CHANGED
@@ -5,7 +5,7 @@
5
5
  // Protocol Constants
6
6
  // ---------------------------------------------------------------------------
7
7
  export const WS_PROTOCOL_VERSION = 1;
8
- export const WS_CLIENT_VERSION = '2.1.1';
8
+ export const WS_CLIENT_VERSION = '2.3.1';
9
9
  // ---------------------------------------------------------------------------
10
10
  // Connection Constants
11
11
  // ---------------------------------------------------------------------------
package/dist/index.d.ts CHANGED
@@ -21,5 +21,5 @@ export type { OfflineQueueConfig } from './services/OfflineQueue';
21
21
  export { EventHandlers } from './handlers/EventHandlers';
22
22
  export { registerAllHandlers } from './handlers/index';
23
23
  export * from './constants';
24
- export declare const WSE_VERSION = "2.1.1";
24
+ export declare const WSE_VERSION = "2.3.1";
25
25
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -44,5 +44,5 @@ export * from './constants';
44
44
  // ---------------------------------------------------------------------------
45
45
  // Version Info
46
46
  // ---------------------------------------------------------------------------
47
- export const WSE_VERSION = '2.1.1';
47
+ export const WSE_VERSION = '2.3.1';
48
48
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wse-client",
3
- "version": "2.2.1",
3
+ "version": "2.3.1",
4
4
  "description": "WSE (WebSocket Engine) React client. Type-safe hooks, auto-reconnect, offline queue, E2E encryption.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",