-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstanceService.js
More file actions
136 lines (111 loc) · 3.72 KB
/
instanceService.js
File metadata and controls
136 lines (111 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import api from './api';
class InstanceService {
constructor() {
this.healthyInstances = [];
this.allInstancesWithStatus = [];
this.loading = false;
this.error = null;
this.lastUpdate = null;
this.listeners = new Set();
this.startHealthChecking();
}
addListener(callback) {
this.listeners.add(callback);
}
removeListener(callback) {
this.listeners.delete(callback);
}
notifyListeners() {
this.listeners.forEach(callback => {
try {
callback({
instances: this.healthyInstances,
allInstances: this.allInstancesWithStatus,
loading: this.loading,
error: this.error,
lastUpdate: this.lastUpdate
});
} catch (err) {
console.error('Error notifying listener:', err);
}
});
}
getHealthyInstances() {
return {
instances: this.healthyInstances,
loading: this.loading,
error: this.error,
lastUpdate: this.lastUpdate
};
}
getAllInstancesWithStatus() {
return {
instances: this.allInstancesWithStatus,
loading: this.loading,
error: this.error,
lastUpdate: this.lastUpdate
};
}
async fetchHealthyInstances() {
try {
const isInitialLoad = this.healthyInstances.length === 0;
if (isInitialLoad) {
this.loading = true;
this.notifyListeners();
console.log('🔄 Loading TES instances with status...');
} else {
console.log('🔄 Refreshing TES instances with status...');
}
const response = await api.get('/api/instances-with-status', {
timeout: 10000
});
const data = response.data;
const allInstances = data.instances || [];
// Filter to only healthy instances, but keep status info
this.healthyInstances = allInstances.filter(inst => inst.status === 'healthy');
// Store all instances (including unhealthy) for dropdown display
this.allInstancesWithStatus = allInstances;
this.lastUpdate = data.last_updated ? new Date(data.last_updated) : new Date();
this.error = null;
console.log(`✅ Got ${this.healthyInstances.length} healthy instances out of ${allInstances.length} total (updated: ${this.lastUpdate.toLocaleTimeString()})`);
} catch (err) {
console.error('Error fetching instances with status:', err);
if (err.code === 'ECONNABORTED') {
this.error = 'Connection timeout - using cached data';
console.warn('Connection timed out, keeping existing instances');
} else if (err.response?.status === 500) {
this.error = 'Server error - using cached data';
} else {
this.error = err.response?.data?.error || err.message || 'Failed to fetch instances';
}
if (this.healthyInstances.length === 0) {
console.warn('No cached instances available');
} else {
console.log(`Using ${this.healthyInstances.length} cached healthy instances during error`);
}
} finally {
this.loading = false;
this.notifyListeners();
}
}
startHealthChecking() {
this.fetchHealthyInstances();
this.healthCheckInterval = setInterval(() => {
this.fetchHealthyInstances();
}, 60000);
console.log('🔄 Started cache refresh every 60 seconds');
}
stopHealthChecking() {
if (this.healthCheckInterval) {
clearInterval(this.healthCheckInterval);
this.healthCheckInterval = null;
console.log('⏹️ Stopped health checking');
}
}
async refresh() {
console.log('🔄 Force refreshing healthy instances...');
await this.fetchHealthyInstances();
}
}
const instanceService = new InstanceService();
export default instanceService;