Pular para o conteúdo principal

Streaming API

Real-time streaming endpoints for live updates.

Overview

Data Stream provides three streaming protocols:

ProtocolEndpoint PatternUse Case
WebSocketws://host/ws/:gameBidirectional, low latency
SSEGET /sse/:gameServer push, auto-reconnect
WebTransporthttps://host:4433/wtUltra-low latency

WebSocket

Endpoints

ws://localhost:3000/ws/:game
ws://localhost:3000/ws/type/:type
wss://datastream.andrebassi.com.br/ws/:game
wss://datastream.andrebassi.com.br/ws/type/:type

Connection

// By game
const ws = new WebSocket('wss://datastream.andrebassi.com.br/ws/crash');

// By type
const ws = new WebSocket('wss://datastream.andrebassi.com.br/ws/type/multiplier');

Message Format

Messages are JSON-encoded round objects:

{
"round_id": 512,
"game_id": 1,
"game_slug": "crash",
"game_type": "multiplier",
"finished_at": "2026-01-17T00:45:42Z",
"extras": "{\"point\": \"11.72\"}",
"timestamp": 1768621542123
}

Events

EventDescription
onopenConnection established
onmessageNew round received
oncloseConnection closed
onerrorError occurred

Example

const ws = new WebSocket('wss://datastream.andrebassi.com.br/ws/crash');

ws.onopen = () => {
console.log('Connected');
};

ws.onmessage = (event) => {
const round = JSON.parse(event.data);
console.log(`Round ${round.round_id}: ${round.extras}`);
};

ws.onclose = (event) => {
console.log(`Closed: ${event.code}`);
// Implement reconnection
};

ws.onerror = (error) => {
console.error('Error:', error);
};

Server-Sent Events (SSE)

Endpoints

GET /sse/:game
GET /sse/type/:type

Headers

Request:

Accept: text/event-stream

Response:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

Event Types

EventDescription
initialFirst message with latest result
messageNew round result
(comment)Heartbeat (: prefix)

Event Format

event: initial
data: {"round_id":512,"game_slug":"crash",...}

: heartbeat 1705432800

event: message
data: {"round_id":513,"game_slug":"crash",...}

Example

const sse = new EventSource('/sse/crash');

// Initial data
sse.addEventListener('initial', (e) => {
const round = JSON.parse(e.data);
console.log('Initial:', round);
});

// New messages
sse.addEventListener('message', (e) => {
const round = JSON.parse(e.data);
console.log('New round:', round);
});

// Connection events
sse.onopen = () => console.log('Connected');
sse.onerror = () => console.log('Reconnecting...');

curl Testing

curl -N https://datastream.andrebassi.com.br/sse/crash

WebTransport

Experimental

WebTransport is disabled by default. See WebTransport docs for setup.

Endpoint

https://datastream.andrebassi.com.br:4433/wt

Connection

const wt = new WebTransport('https://datastream.andrebassi.com.br:4433/wt');
await wt.ready;

Datagrams

WebTransport uses unreliable datagrams for lowest latency:

const reader = wt.datagrams.readable.getReader();

while (true) {
const { value, done } = await reader.read();
if (done) break;

const text = new TextDecoder().decode(value);
const round = JSON.parse(text);
console.log('Datagram:', round);
}

Message Schema

All streaming protocols use the same message format:

interface Round {
round_id: number; // Unique identifier
game_id: number; // Database ID
game_slug: string; // URL-friendly name
game_type: string; // Category
finished_at: string; // ISO 8601 timestamp
extras: string; // JSON-encoded game data
timestamp: number; // Unix milliseconds
}

Extras Schema

Crash

{"point": "11.72"}

Double

{"color": "red", "number": 5}

Slot

{"reels": ["cherry", "lemon", "orange"], "multiplier": "2.00"}

Wall Street

{"trending": "up"}

Subscription Patterns

By Game

Subscribe to a specific game:

/ws/crash        → Only crash results
/sse/double → Only double results

By Type

Subscribe to all games of a type:

/ws/type/multiplier   → crash + slot results
/sse/type/color → double results

Latency Characteristics

ProtocolTypical LatencyNotes
WebSocket1-5msTCP overhead
SSE10-50msHTTP chunked
WebTransport0.5-2msUDP datagrams

Latency Measurement

Each message includes a timestamp field (Unix ms). Calculate latency:

ws.onmessage = (event) => {
const round = JSON.parse(event.data);
const latency = Date.now() - round.timestamp;
console.log(`Latency: ${latency}ms`);
};

Connection Management

WebSocket Reconnection

class ReconnectingWebSocket {
constructor(url) {
this.url = url;
this.ws = null;
this.reconnectDelay = 1000;
this.maxDelay = 30000;
}

connect() {
this.ws = new WebSocket(this.url);

this.ws.onopen = () => {
this.reconnectDelay = 1000;
};

this.ws.onclose = () => {
this.scheduleReconnect();
};
}

scheduleReconnect() {
setTimeout(() => {
this.connect();
}, this.reconnectDelay);

// Exponential backoff
this.reconnectDelay = Math.min(
this.reconnectDelay * 2,
this.maxDelay
);
}
}

SSE (Auto-Reconnect)

SSE reconnects automatically. Just handle the error event:

sse.onerror = () => {
console.log('Connection lost, auto-reconnecting...');
// Browser handles reconnection
};

Error Handling

WebSocket Errors

CodeMeaningAction
1000Normal closeClean shutdown
1001Going awayServer restart
1006AbnormalNetwork issue
1011Server errorRetry with backoff

SSE Errors

SSE auto-reconnects on network errors. Handle via:

sse.onerror = (event) => {
if (event.target.readyState === EventSource.CLOSED) {
console.log('Connection closed');
} else {
console.log('Reconnecting...');
}
};

Best Practices

1. Choose the Right Protocol

// SSE for simple server push
if (needsOnlyServerPush) {
return new EventSource('/sse/crash');
}

// WebSocket for bidirectional
if (needsBidirectional) {
return new WebSocket('wss://host/ws/crash');
}

// WebTransport for lowest latency
if (typeof WebTransport !== 'undefined' && needsLowestLatency) {
return new WebTransport('https://host:4433/wt');
}

2. Handle Reconnection

Always implement reconnection for WebSocket:

ws.onclose = () => {
setTimeout(() => connect(), 3000);
};

3. Parse Extras Safely

function parseExtras(extras) {
try {
return JSON.parse(extras);
} catch (e) {
console.error('Invalid extras:', extras);
return {};
}
}

4. Monitor Latency

function handleMessage(round) {
const latency = Date.now() - round.timestamp;
if (latency > 100) {
console.warn(`High latency: ${latency}ms`);
}
}

5. Graceful Degradation

async function connect() {
// Try best protocol first
if (typeof WebTransport !== 'undefined') {
try {
return await connectWebTransport();
} catch (e) {}
}

try {
return await connectWebSocket();
} catch (e) {}

// Fallback to SSE
return connectSSE();
}