Skip to content

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:

curl http://localhost:8080/api/v1/simulations/9a1d5f7e-3b2c-4d9e-8f1a-6c2b4a7d9e3f/ws-info


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 WebSocket
  • gecko.rest.api.dto.WebSocketInfoDto - WebSocket endpoint discovery response
  • gecko.rest.api.config.WebSocketConfig - Spring WebSocket/STOMP configuration
  • gecko.rest.api.controller.WebSocketController - WebSocket endpoint handlers
  • gecko.rest.api.service.SimulationProgressBroadcaster - Unified broadcast service (refactored from v2.20.0)

REST API Endpoints Added:

  • GET /api/v1/simulations/{id}/ws-info - WebSocket discovery
  • SUBSCRIBE /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


See Also