Real-time Updates
Veltix provides powerful real-time update capabilities that enable your dashboards to display live data with minimal latency.
Overview
Real-time updates in Veltix support:
- WebSocket Connections: Direct WebSocket communication
- Polling Updates: Regular HTTP polling for data changes
- Server-Sent Events: One-way real-time data streaming
- Push Notifications: Instant data push to connected clients
- Connection Management: Automatic reconnection and error handling
Update Modes
1. WebSocket Updates
Direct WebSocket connections for real-time bidirectional communication.
// WebSocket data source configuration
const websocketDataSource = {
type: 'websocket',
url: 'ws://localhost:3001/realtime',
protocols: ['realtime-protocol'],
reconnect: true,
reconnectInterval: 5000,
maxReconnectAttempts: 10,
onMessage: (data) => {
console.log('Real-time data received:', data);
},
onError: (error) => {
console.error('WebSocket error:', error);
}
};
// Using WebSocket data source
<BarChart
dataSource={websocketDataSource}
xField="timestamp"
yField="value"
realTime={true}
/>2. Polling Updates
Regular HTTP polling for data that doesn’t require immediate updates.
// Polling data source configuration
const pollingDataSource = {
type: 'api',
url: 'https://api.example.com/sales',
refreshInterval: 30000, // 30 seconds
refreshMode: 'polling',
onUpdate: (data) => {
console.log('Data updated via polling:', data);
},
onError: (error) => {
console.error('Polling error:', error);
}
};
// Using polling data source
<LineChart
dataSource={pollingDataSource}
xField="date"
yField="sales"
realTime={true}
/>3. Server-Sent Events
One-way real-time data streaming from server to client.
// SSE data source configuration
const sseDataSource = {
type: 'sse',
url: 'https://api.example.com/events',
eventTypes: ['data-update', 'status-change'],
onMessage: (event) => {
console.log('SSE event received:', event);
},
onError: (error) => {
console.error('SSE error:', error);
}
};
// Using SSE data source
<PieChart
dataSource={sseDataSource}
nameField="category"
valueField="amount"
realTime={true}
/>Connection Management
WebSocket Connection
import { useWebSocket } from '@veltix/pusher';
function RealTimeComponent() {
const {
connection,
send,
subscribe,
unsubscribe,
isConnected,
reconnect
} = useWebSocket({
url: 'ws://localhost:3001/realtime',
options: {
reconnect: true,
reconnectInterval: 5000,
maxReconnectAttempts: 10
}
});
// Subscribe to data updates
useEffect(() => {
const unsubscribe = subscribe('sales-updates', (data) => {
console.log('Sales data updated:', data);
});
return () => unsubscribe();
}, [subscribe]);
// Send message to server
const sendUpdate = () => {
send('request-update', { type: 'sales', period: 'daily' });
};
return (
<div>
<div>Connection Status: {isConnected ? 'Connected' : 'Disconnected'}</div>
<button onClick={sendUpdate}>Request Update</button>
<button onClick={reconnect}>Reconnect</button>
</div>
);
}Connection State Management
// Connection state hook
const useConnectionState = () => {
const [state, setState] = useState({
isConnected: false,
isConnecting: false,
isReconnecting: false,
lastError: null,
connectionCount: 0
});
const updateState = useCallback((updates) => {
setState(prev => ({ ...prev, ...updates }));
}, []);
return { state, updateState };
};
// Connection monitoring
const useConnectionMonitor = (connection) => {
useEffect(() => {
const handleConnect = () => {
console.log('Connected to real-time service');
};
const handleDisconnect = () => {
console.log('Disconnected from real-time service');
};
const handleError = (error) => {
console.error('Connection error:', error);
};
connection.on('connect', handleConnect);
connection.on('disconnect', handleDisconnect);
connection.on('error', handleError);
return () => {
connection.off('connect', handleConnect);
connection.off('disconnect', handleDisconnect);
connection.off('error', handleError);
};
}, [connection]);
};Data Synchronization
Real-time Data Binding
// Real-time data binding
const useRealTimeData = (dataSource) => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
if (dataSource.type === 'websocket') {
const connection = new WebSocket(dataSource.url);
connection.onmessage = (event) => {
const newData = JSON.parse(event.data);
setData(newData);
};
connection.onerror = (error) => {
setError(error);
};
return () => {
connection.close();
};
}
}, [dataSource]);
return { data, loading, error };
};
// Using real-time data
function RealTimeChart({ dataSource }) {
const { data, loading, error } = useRealTimeData(dataSource);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<BarChart
data={data}
xField="timestamp"
yField="value"
realTime={true}
/>
);
}Data Transformation
// Real-time data transformation
const useRealTimeTransform = (data, transforms) => {
const transformedData = useMemo(() => {
return transforms.reduce((acc, transform) => {
switch (transform.type) {
case 'filter':
return acc.filter(item =>
item[transform.field] === transform.value
);
case 'sort':
return acc.sort((a, b) =>
a[transform.field] - b[transform.field]
);
case 'aggregate':
return aggregateData(acc, transform);
default:
return acc;
}
}, data);
}, [data, transforms]);
return transformedData;
};
// Using transformed real-time data
function TransformedRealTimeChart({ data, transforms }) {
const transformedData = useRealTimeTransform(data, transforms);
return (
<LineChart
data={transformedData}
xField="timestamp"
yField="value"
realTime={true}
/>
);
}Performance Optimization
Efficient Updates
// Optimized real-time updates
const useOptimizedRealTime = (dataSource, options = {}) => {
const {
throttle = 100, // Throttle updates to 100ms
batchUpdates = true, // Batch multiple updates
maxDataPoints = 1000 // Limit data points for performance
} = options;
const [data, setData] = useState([]);
const updateQueue = useRef([]);
const lastUpdate = useRef(0);
const processUpdate = useCallback((newData) => {
const now = Date.now();
if (batchUpdates) {
updateQueue.current.push(newData);
if (now - lastUpdate.current > throttle) {
const batchedData = updateQueue.current;
updateQueue.current = [];
lastUpdate.current = now;
setData(prevData => {
const updatedData = [...prevData, ...batchedData];
// Limit data points for performance
return updatedData.slice(-maxDataPoints);
});
}
} else {
setData(prevData => {
const updatedData = [...prevData, newData];
return updatedData.slice(-maxDataPoints);
});
}
}, [throttle, batchUpdates, maxDataPoints]);
return { data, processUpdate };
};Memory Management
// Memory-efficient real-time data
const useMemoryOptimizedRealTime = (maxPoints = 1000) => {
const [data, setData] = useState([]);
const dataRef = useRef([]);
const addDataPoint = useCallback((newPoint) => {
dataRef.current = [...dataRef.current, newPoint];
// Keep only the latest data points
if (dataRef.current.length > maxPoints) {
dataRef.current = dataRef.current.slice(-maxPoints);
}
setData([...dataRef.current]);
}, [maxPoints]);
const clearData = useCallback(() => {
dataRef.current = [];
setData([]);
}, []);
return { data, addDataPoint, clearData };
};Error Handling
Connection Error Handling
// Robust error handling for real-time connections
const useRealTimeErrorHandling = (connection) => {
const [error, setError] = useState(null);
const [retryCount, setRetryCount] = useState(0);
const maxRetries = 5;
const handleError = useCallback((error) => {
console.error('Real-time connection error:', error);
setError(error);
if (retryCount < maxRetries) {
setTimeout(() => {
setRetryCount(prev => prev + 1);
connection.reconnect();
}, Math.pow(2, retryCount) * 1000); // Exponential backoff
}
}, [connection, retryCount, maxRetries]);
const resetError = useCallback(() => {
setError(null);
setRetryCount(0);
}, []);
useEffect(() => {
connection.on('error', handleError);
connection.on('connect', resetError);
return () => {
connection.off('error', handleError);
connection.off('connect', resetError);
};
}, [connection, handleError, resetError]);
return { error, retryCount, resetError };
};Data Validation
// Real-time data validation
const validateRealTimeData = (data, schema) => {
try {
// Validate data structure
if (!Array.isArray(data)) {
throw new Error('Data must be an array');
}
// Validate each data point
const validatedData = data.map((item, index) => {
const { error } = schema.validate(item);
if (error) {
throw new Error(`Invalid data at index ${index}: ${error.message}`);
}
return item;
});
return { valid: true, data: validatedData };
} catch (error) {
return { valid: false, error: error.message };
}
};
// Using data validation
const useValidatedRealTimeData = (dataSource, schema) => {
const [data, setData] = useState([]);
const [validationError, setValidationError] = useState(null);
useEffect(() => {
const handleData = (rawData) => {
const validation = validateRealTimeData(rawData, schema);
if (validation.valid) {
setData(validation.data);
setValidationError(null);
} else {
setValidationError(validation.error);
console.error('Data validation failed:', validation.error);
}
};
// Subscribe to data updates
dataSource.on('data', handleData);
return () => {
dataSource.off('data', handleData);
};
}, [dataSource, schema]);
return { data, validationError };
};Configuration Examples
WebSocket Configuration
// Advanced WebSocket configuration
const advancedWebSocketConfig = {
url: 'wss://api.example.com/realtime',
protocols: ['realtime-v1'],
options: {
reconnect: true,
reconnectInterval: 5000,
maxReconnectAttempts: 10,
heartbeat: 30000,
timeout: 10000,
compression: true
},
authentication: {
type: 'jwt',
token: 'your-jwt-token'
},
subscriptions: [
'sales-updates',
'inventory-changes',
'user-activity'
]
};Polling Configuration
// Advanced polling configuration
const advancedPollingConfig = {
url: 'https://api.example.com/data',
interval: 30000, // 30 seconds
options: {
retryAttempts: 3,
retryDelay: 1000,
timeout: 5000,
headers: {
'Authorization': 'Bearer your-token'
}
},
dataTransformation: (data) => {
return data.map(item => ({
...item,
timestamp: new Date(item.timestamp),
value: parseFloat(item.value)
}));
},
errorHandling: {
onError: (error) => {
console.error('Polling error:', error);
// Implement fallback strategy
},
fallbackData: []
}
};Best Practices
1. Connection Management
- Implement automatic reconnection
- Use exponential backoff for retries
- Monitor connection health
- Handle connection errors gracefully
2. Data Handling
- Validate incoming data
- Implement data transformation
- Limit data points for performance
- Use efficient data structures
3. Performance
- Throttle frequent updates
- Batch multiple updates
- Implement memory management
- Monitor resource usage
4. Error Handling
- Implement comprehensive error handling
- Provide fallback mechanisms
- Log errors for debugging
- Graceful degradation
5. Security
- Use secure WebSocket connections (WSS)
- Implement proper authentication
- Validate all incoming data
- Monitor for suspicious activity
Troubleshooting
Common Issues
Connection not establishing
- Check WebSocket URL and protocol
- Verify server is running
- Check firewall settings
- Test with simple WebSocket client
Data not updating
- Verify subscription to correct channels
- Check data format and structure
- Monitor connection status
- Review error logs
Performance issues
- Reduce update frequency
- Implement data throttling
- Limit data points
- Use efficient data structures
Memory leaks
- Clean up event listeners
- Limit data storage
- Implement proper cleanup
- Monitor memory usage
Last updated on