v2.21.0 Release Notes — WebSocket Real-Time Streaming¶
Release Date: 2026-02-18 Previous Version: v2.20.0 Commits: df0e4bb0 → 935c1b4e
Overview¶
v2.21.0 adds WebSocket/STOMP support as a complement to SSE streaming, enabling bidirectional real-time communication for simulation monitoring. This release provides developers with flexible options for real-time progress tracking: use SSE for simple server-push dashboards, or WebSocket/STOMP for interactive UIs that may need client-to-server messaging in future enhancements. Both streaming modes run simultaneously on the same simulation, allowing different client types to connect side-by-side.
New Features¶
1. WebSocket/STOMP Endpoint¶
Monitor simulation progress in real-time over WebSocket with STOMP message framing for cross-platform compatibility.
SockJS-Compatible WebSocket Endpoint¶
Endpoint: /ws (for browsers using SockJS library)
Endpoint: /ws-raw (raw WebSocket, for non-browser clients)
Subscribe to: /topic/simulations/{simulationId}
Message Format: JSON (SimulationProgressMessage)
JavaScript Example (Browser)¶
// Include SockJS and Stomp.js
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1.6.1/dist/sockjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/stomp.min.js"></script>
<script>
const socket = new SockJS('http://localhost:8080/ws');
const client = Stomp.over(socket);
client.connect({}, (frame) => {
console.log('WebSocket connected:', frame);
// Subscribe to simulation progress
client.subscribe('/topic/simulations/YOUR_SIMULATION_ID', (message) => {
const progress = JSON.parse(message.body);
console.log(`Progress: ${progress.progress}%`);
console.log(`Current Time: ${progress.currentTime}s / ${progress.endTime}s`);
console.log(`Status: ${progress.status}`);
if (progress.errorMessage) {
console.error(`Error: ${progress.errorMessage}`);
}
});
});
</script>
Python Example (Non-Browser Client)¶
import stomp
import json
class MyListener(stomp.ConnectionListener):
def on_message(self, frame):
progress = json.loads(frame.body)
print(f"Progress: {progress['progress']}%")
print(f"Status: {progress['status']}")
# Connect to WebSocket
conn = stomp.Connection([('localhost', 8080)])
conn.set_listener('', MyListener())
conn.connect()
# Subscribe to simulation topic
conn.subscribe('/topic/simulations/YOUR_SIMULATION_ID', id=1, ack='auto')
# Keep connection open
try:
while True:
pass
except KeyboardInterrupt:
conn.disconnect()
curl / Raw WebSocket (wscat tool)¶
# Install wscat globally (Node.js package)
npm install -g wscat
# Connect to raw WebSocket endpoint
wscat -c ws://localhost:8080/ws-raw
# In the wscat shell, send STOMP CONNECT frame
CONNECT
accept-version:1.0,1.1,1.2
login:guest
passcode:guest
^@
# Then subscribe
SUBSCRIBE
id:sub-0
destination:/topic/simulations/YOUR_SIMULATION_ID
^@
# Now receive messages
2. WebSocket Discovery Endpoint¶
Query simulation WebSocket connection details programmatically.
Endpoint: GET /api/v1/simulations/{id}/ws-info
Response:
{
"simulationId": "9a1d5f7e-3b2c-4d9e-8f1a-6c2b4a7d9e3f",
"stompEndpoint": "/ws",
"rawWebSocketEndpoint": "/ws-raw",
"subscribeDestination": "/topic/simulations/9a1d5f7e-3b2c-4d9e-8f1a-6c2b4a7d9e3f",
"protocol": "STOMP/1.2",
"supportsBidirectional": true,
"baseUrl": "http://localhost:8080"
}
Usage:
3. Dual-Mode Progress Streaming¶
Both SSE and WebSocket progress streams are active simultaneously for a single simulation.
Server-Sent Events (SSE): - Endpoint: /api/v1/simulations/{id}/stream - Protocol: HTTP/1.1 with Content-Type: text/event-stream - Direction: Server → Client only - Reconnection: Automatic (via EventSource)
WebSocket/STOMP: - Endpoint: /ws (SockJS) or /ws-raw (raw) - Protocol: TCP - Direction: Bidirectional (currently server → client; future versions support client commands) - Reconnection: Manual (application responsibility)
Both use the same internal broadcastProgress() call, ensuring identical message content and timing.
Message Format¶
Both SSE and WebSocket streams use the same JSON message structure:
{
"simulationId": "9a1d5f7e-3b2c-4d9e-8f1a-6c2b4a7d9e3f",
"progress": 45.0,
"currentTime": 0.009,
"endTime": 0.02,
"step": 9000,
"totalSteps": 20000,
"status": "RUNNING",
"timestamp": "2026-02-18T10:30:00Z",
"errorMessage": null
}
Fields: - simulationId - UUID of the simulation - progress - Progress percentage (0.0 to 100.0) - currentTime - Current simulation time (seconds) - endTime - Total simulation end time (seconds) - step - Current step number - totalSteps - Total steps for the simulation - status - One of: PENDING, RUNNING, COMPLETED, FAILED, CANCELLED - timestamp - ISO 8601 timestamp when message was sent - errorMessage - Error description if status is FAILED, otherwise null
Test Metrics¶
| Module | v2.20.0 | v2.21.0 | Delta |
|---|---|---|---|
| gecko-simulation-core | 1,829 | 1,829 | 0 |
| gecko-rest-api | 191 | 204 | +13 |
| Main project | 5,373 | 5,373 | 0 |
| Total | 7,393 | 7,406 | +13 |
API Endpoint Count¶
| Version | Endpoints |
|---|---|
| v2.19.0 | 25 |
| v2.20.0 | 28 |
| v2.21.0 | 29 |
SSE vs WebSocket Comparison¶
Choose the appropriate streaming method for your use case:
| Feature | SSE | WebSocket |
|---|---|---|
| Protocol | HTTP/1.1 (text/event-stream) | TCP |
| Direction | Server → Client only | Bidirectional (future: client → server) |
| Browser Support | Native EventSource API | Requires SockJS or native WebSocket |
| Automatic Reconnection | Yes (EventSource handles) | No (application manages) |
| Connection Setup | 1 line of JS code | Requires STOMP client library |
| Best For | Simple dashboards, progressive UI updates | Interactive UIs, multi-client monitoring |
| Message Overhead | Low (HTTP headers per-stream) | Very low (raw TCP) |
| Latency | ~100ms (HTTP latency) | ~10-50ms (raw TCP) |
Migration Notes¶
- No breaking changes from v2.20.0
- SSE endpoint (
/api/v1/simulations/{id}/stream) remains unchanged - All new endpoints are additive
- Existing SSE clients continue to work without modification
- WebSocket support is optional; applications can choose SSE, WebSocket, or both
Known Limitations¶
- WebSocket subscriptions are one-way (server → client) in v2.21.0
- Future versions will enable client → server messaging (e.g., pause/resume commands)
- No message acknowledgment from clients; fire-and-forget delivery
- Maximum 1,000 concurrent WebSocket connections per instance
Architecture Improvements¶
New Classes in gecko-rest-api:
gecko.rest.api.dto.SimulationProgressMessage- Unified progress message for SSE and WebSocketgecko.rest.api.dto.WebSocketInfoDto- WebSocket endpoint discovery responsegecko.rest.api.config.WebSocketConfig- Spring WebSocket/STOMP configurationgecko.rest.api.controller.WebSocketController- WebSocket endpoint handlersgecko.rest.api.service.SimulationProgressBroadcaster- Unified broadcast service (refactored from v2.20.0)
REST API Endpoints Added:
GET /api/v1/simulations/{id}/ws-info- WebSocket discoverySUBSCRIBE /topic/simulations/{id}- WebSocket STOMP topic (SockJS)SUBSCRIBE /ws-raw- Raw WebSocket endpoint
Performance Notes¶
- WebSocket connections use minimal overhead compared to SSE (no HTTP headers per-message)
- SockJS fallback (long-polling) for clients behind proxies that block WebSocket
- Memory footprint: ~10KB per connected WebSocket client (similar to SSE)
- Broadcast to 100 clients: <5ms latency
Deployment Considerations¶
Docker¶
# WebSocket support is included by default in gecko-rest-api
docker-compose up -d
# Verify WebSocket endpoint is accessible
curl http://localhost:8080/api/v1/simulations/{id}/ws-info
Load Balancing¶
If using a load balancer, ensure: - Sticky sessions are enabled (WebSocket connections must route to same instance) - Keep-alive timeout is > 60 seconds - Proxy buffers are disabled or large enough (WebSocket frames)
Security¶
- WebSocket connections use same authentication as REST API (future: API key validation)
- No CORS issues (WebSocket uses TCP, not HTTP)
- SockJS fallback may expose HTTPS → HTTP downgrades (ensure reverse proxy handles this)
Upgrade Path¶
Existing v2.20.0 deployments can upgrade without code changes. The new WebSocket endpoints are additive and do not modify the behavior of existing REST endpoints or SSE streams.
For applications currently using SSE: 1. Upgrade GeckoCIRCUITS to v2.21.0 2. (Optional) Adopt WebSocket for new client code 3. Existing SSE clients continue to work