feat: live updates

This commit is contained in:
2025-10-14 20:51:48 +02:00
parent 6db56e470c
commit 25911a183c
9 changed files with 825 additions and 52 deletions

View File

@@ -21,45 +21,124 @@ class ClusterViewModel extends ViewModel {
setTimeout(() => {
this.updatePrimaryNodeDisplay();
}, 100);
// Set up WebSocket listeners for real-time updates
this.setupWebSocketListeners();
}
// Set up WebSocket event listeners
setupWebSocketListeners() {
if (!window.wsClient) {
logger.warn('WebSocket client not available');
return;
}
// Listen for cluster updates
window.wsClient.on('clusterUpdate', (data) => {
logger.debug('ClusterViewModel: Received WebSocket cluster update:', data);
// Update members from WebSocket data
if (data.members && Array.isArray(data.members)) {
const onlineNodes = data.members.filter(m => m && m.status && m.status.toUpperCase() === 'ACTIVE').length;
logger.debug(`ClusterViewModel: Updating members from ${this.get('members')?.length || 0} to ${data.members.length} members`);
this.batchUpdate({
members: data.members,
lastUpdateTime: data.timestamp || new Date().toISOString(),
onlineNodes: onlineNodes
});
// Update primary node display if it changed
if (data.primaryNode !== this.get('primaryNode')) {
logger.debug(`ClusterViewModel: Primary node changed from ${this.get('primaryNode')} to ${data.primaryNode}`);
this.set('primaryNode', data.primaryNode);
this.set('totalNodes', data.totalNodes || 0);
}
} else {
logger.warn('ClusterViewModel: Received cluster update but no valid members array:', data);
}
});
// Listen for node discovery events
window.wsClient.on('nodeDiscovery', (data) => {
logger.debug('ClusterViewModel: Received WebSocket node discovery event:', data);
if (data.action === 'discovered') {
// A new node was discovered - trigger a cluster update
setTimeout(() => {
this.updateClusterMembers();
}, 500);
} else if (data.action === 'stale') {
// A node became stale - trigger a cluster update
setTimeout(() => {
this.updateClusterMembers();
}, 500);
}
});
// Listen for connection status changes
window.wsClient.on('connected', () => {
logger.debug('ClusterViewModel: WebSocket connected');
// Optionally trigger an immediate update when connection is restored
setTimeout(() => {
this.updateClusterMembers();
}, 1000);
});
window.wsClient.on('disconnected', () => {
logger.debug('ClusterViewModel: WebSocket disconnected');
});
}
// Update cluster members
async updateClusterMembers() {
try {
logger.debug('ClusterViewModel: updateClusterMembers called');
// Check if we have recent WebSocket data (within last 30 seconds)
const lastUpdateTime = this.get('lastUpdateTime');
const now = new Date();
const websocketDataAge = lastUpdateTime ? (now - new Date(lastUpdateTime)) : Infinity;
// If WebSocket data is recent, skip REST API call to avoid conflicts
if (websocketDataAge < 30000 && this.get('members').length > 0) {
logger.debug('ClusterViewModel: Using recent WebSocket data, skipping REST API call');
return;
}
// Store current UI state before update
const currentUIState = this.getAllUIState();
const currentExpandedCards = this.get('expandedCards');
const currentActiveTabs = this.get('activeTabs');
this.set('isLoading', true);
this.set('error', null);
logger.debug('ClusterViewModel: Fetching cluster members...');
const response = await window.apiClient.getClusterMembers();
logger.debug('ClusterViewModel: Got response:', response);
const members = response.members || [];
const onlineNodes = Array.isArray(members)
? members.filter(m => m && m.status && m.status.toUpperCase() === 'ACTIVE').length
: 0;
// Use batch update
this.batchUpdate({
members: members,
lastUpdateTime: new Date().toISOString(),
onlineNodes: onlineNodes
});
// Restore expanded cards and active tabs
this.set('expandedCards', currentExpandedCards);
this.set('activeTabs', currentActiveTabs);
// Update primary node display
logger.debug('ClusterViewModel: Updating primary node display...');
await this.updatePrimaryNodeDisplay();
} catch (error) {
console.error('ClusterViewModel: Failed to fetch cluster members:', error);
this.set('error', error.message);