223 lines
7.0 KiB
JavaScript
223 lines
7.0 KiB
JavaScript
/**
|
|
* Polling-based Live Updates for ANNOTATE
|
|
* Replaces WebSocket with simple polling (like clean_dashboard)
|
|
*/
|
|
|
|
class LiveUpdatesPolling {
|
|
constructor() {
|
|
this.pollInterval = null;
|
|
this.pollDelay = 2000; // Poll every 2 seconds (like clean_dashboard)
|
|
this.subscriptions = new Set();
|
|
this.isPolling = false;
|
|
|
|
// Callbacks
|
|
this.onChartUpdate = null;
|
|
this.onPredictionUpdate = null;
|
|
this.onConnectionChange = null;
|
|
|
|
console.log('LiveUpdatesPolling initialized');
|
|
}
|
|
|
|
start() {
|
|
if (this.isPolling) {
|
|
console.log('Already polling');
|
|
return;
|
|
}
|
|
|
|
this.isPolling = true;
|
|
this._startPolling();
|
|
|
|
if (this.onConnectionChange) {
|
|
this.onConnectionChange(true);
|
|
}
|
|
|
|
console.log('Started polling for live updates');
|
|
}
|
|
|
|
stop() {
|
|
if (this.pollInterval) {
|
|
clearInterval(this.pollInterval);
|
|
this.pollInterval = null;
|
|
}
|
|
this.isPolling = false;
|
|
|
|
if (this.onConnectionChange) {
|
|
this.onConnectionChange(false);
|
|
}
|
|
|
|
console.log('Stopped polling for live updates');
|
|
}
|
|
|
|
_startPolling() {
|
|
// Poll immediately, then set interval
|
|
this._poll();
|
|
this.pollInterval = setInterval(() => {
|
|
this._poll();
|
|
}, this.pollDelay);
|
|
}
|
|
|
|
_poll() {
|
|
// Poll each subscription
|
|
this.subscriptions.forEach(sub => {
|
|
fetch('/api/live-updates', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
symbol: sub.symbol,
|
|
timeframe: sub.timeframe
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Handle chart update
|
|
if (data.chart_update && this.onChartUpdate) {
|
|
this.onChartUpdate(data.chart_update);
|
|
}
|
|
|
|
// Handle prediction update
|
|
if (data.prediction && this.onPredictionUpdate) {
|
|
this.onPredictionUpdate(data.prediction);
|
|
}
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.debug('Polling error:', error);
|
|
});
|
|
});
|
|
}
|
|
|
|
subscribe(symbol, timeframe) {
|
|
const key = `${symbol}_${timeframe}`;
|
|
this.subscriptions.add({ symbol, timeframe, key });
|
|
|
|
// Auto-start polling if not already started
|
|
if (!this.isPolling) {
|
|
this.start();
|
|
}
|
|
|
|
console.log(`Subscribed to live updates: ${symbol} ${timeframe}`);
|
|
}
|
|
|
|
unsubscribe(symbol, timeframe) {
|
|
const key = `${symbol}_${timeframe}`;
|
|
this.subscriptions.forEach(sub => {
|
|
if (sub.key === key) {
|
|
this.subscriptions.delete(sub);
|
|
}
|
|
});
|
|
|
|
// Stop polling if no subscriptions
|
|
if (this.subscriptions.size === 0) {
|
|
this.stop();
|
|
}
|
|
|
|
console.log(`Unsubscribed from live updates: ${symbol} ${timeframe}`);
|
|
}
|
|
|
|
isConnected() {
|
|
return this.isPolling;
|
|
}
|
|
}
|
|
|
|
// Global instance
|
|
window.liveUpdatesPolling = null;
|
|
|
|
// Initialize on page load
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Initialize polling
|
|
window.liveUpdatesPolling = new LiveUpdatesPolling();
|
|
|
|
// Setup callbacks (same interface as WebSocket version)
|
|
window.liveUpdatesPolling.onConnectionChange = function(connected) {
|
|
const statusElement = document.getElementById('ws-connection-status');
|
|
if (statusElement) {
|
|
if (connected) {
|
|
statusElement.innerHTML = '<span class="badge bg-success">Live</span>';
|
|
} else {
|
|
statusElement.innerHTML = '<span class="badge bg-secondary">Offline</span>';
|
|
}
|
|
}
|
|
};
|
|
|
|
window.liveUpdatesPolling.onChartUpdate = function(data) {
|
|
// Update chart with new candle
|
|
if (window.appState && window.appState.chartManager) {
|
|
window.appState.chartManager.updateLatestCandle(data.symbol, data.timeframe, data.candle);
|
|
}
|
|
};
|
|
|
|
window.liveUpdatesPolling.onPredictionUpdate = function(data) {
|
|
// Update prediction visualization on charts
|
|
if (window.appState && window.appState.chartManager) {
|
|
window.appState.chartManager.updatePredictions(data);
|
|
}
|
|
|
|
// Update prediction display
|
|
if (typeof updatePredictionDisplay === 'function') {
|
|
updatePredictionDisplay(data);
|
|
}
|
|
|
|
// Add to prediction history
|
|
if (typeof predictionHistory !== 'undefined') {
|
|
predictionHistory.unshift(data);
|
|
if (predictionHistory.length > 5) {
|
|
predictionHistory = predictionHistory.slice(0, 5);
|
|
}
|
|
if (typeof updatePredictionHistory === 'function') {
|
|
updatePredictionHistory();
|
|
}
|
|
}
|
|
};
|
|
|
|
// Function to subscribe to all active timeframes
|
|
function subscribeToActiveTimeframes() {
|
|
if (window.appState && window.appState.currentSymbol && window.appState.currentTimeframes) {
|
|
const symbol = window.appState.currentSymbol;
|
|
window.appState.currentTimeframes.forEach(timeframe => {
|
|
window.liveUpdatesPolling.subscribe(symbol, timeframe);
|
|
});
|
|
console.log(`Subscribed to live updates for ${symbol}: ${window.appState.currentTimeframes.join(', ')}`);
|
|
}
|
|
}
|
|
|
|
// Auto-start polling
|
|
console.log('Auto-starting polling for live updates...');
|
|
window.liveUpdatesPolling.start();
|
|
|
|
// Wait for DOM and appState to be ready, then subscribe
|
|
function initializeSubscriptions() {
|
|
// Wait a bit for charts to initialize
|
|
setTimeout(() => {
|
|
subscribeToActiveTimeframes();
|
|
}, 2000);
|
|
}
|
|
|
|
// Subscribe when DOM is ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initializeSubscriptions);
|
|
} else {
|
|
initializeSubscriptions();
|
|
}
|
|
|
|
// Also monitor for appState changes (fallback)
|
|
let lastTimeframes = null;
|
|
setInterval(() => {
|
|
if (window.appState && window.appState.currentTimeframes && window.appState.chartManager) {
|
|
const currentTimeframes = window.appState.currentTimeframes.join(',');
|
|
if (currentTimeframes !== lastTimeframes) {
|
|
lastTimeframes = currentTimeframes;
|
|
subscribeToActiveTimeframes();
|
|
}
|
|
}
|
|
}, 3000);
|
|
});
|
|
|
|
// Cleanup on page unload
|
|
window.addEventListener('beforeunload', function() {
|
|
if (window.liveUpdatesPolling) {
|
|
window.liveUpdatesPolling.stop();
|
|
}
|
|
});
|
|
|