-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest-middleware.js
More file actions
266 lines (218 loc) · 10.2 KB
/
test-middleware.js
File metadata and controls
266 lines (218 loc) · 10.2 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/**
* Middleware Test Scenarios
*
* Run these tests to see your middleware in action!
* Make sure all services are running first:
* - Terminal 1: RabbitMQ (docker-compose up -d)
* - Terminal 2: Mock ROS (npm run dev:mock-ros)
* - Terminal 3: REST Adapter (node adapters/rest-adapter/index.js)
* - Terminal 4: ROS Worker (node workers/ros-worker/index.js)
*/
import fetch from 'node-fetch';
const ADAPTER_URL = 'http://localhost:3001';
const COLORS = {
reset: '\x1b[0m',
bright: '\x1b[1m',
green: '\x1b[32m',
blue: '\x1b[34m',
yellow: '\x1b[33m',
cyan: '\x1b[36m'
};
function log(message, color = 'reset') {
console.log(`${COLORS[color]}${message}${COLORS.reset}`);
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Scenario 1: Single Request
*/
async function scenario1() {
log('\n═══════════════════════════════════════════════════', 'bright');
log('SCENARIO 1: Single Request Through Middleware', 'cyan');
log('═══════════════════════════════════════════════════', 'bright');
log('\n📤 Sending route optimization request...', 'blue');
const response = await fetch(`${ADAPTER_URL}/api/routes/optimize`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
packageId: 'PKG-TEST-001',
address: '123 Middleware Street, Colombo',
priority: 'high',
deliveryWindow: new Date(Date.now() + 3600000).toISOString()
})
});
const data = await response.json();
log('\n✅ Response received:', 'green');
console.log(JSON.stringify(data, null, 2));
log('\n📊 What happened:', 'yellow');
log(' 1. REST Adapter received HTTP request');
log(' 2. Adapter published message to RabbitMQ');
log(' 3. ROS Worker picked up message from queue');
log(' 4. Worker called Mock ROS service');
log(' 5. Worker sent response back through RabbitMQ');
log(' 6. Adapter received response and returned to us!');
}
/**
* Scenario 2: Load Testing (10 concurrent requests)
*/
async function scenario2() {
log('\n═══════════════════════════════════════════════════', 'bright');
log('SCENARIO 2: Load Testing (10 Requests)', 'cyan');
log('═══════════════════════════════════════════════════', 'bright');
log('\n📤 Sending 10 requests simultaneously...', 'blue');
log('👀 Watch RabbitMQ dashboard: http://localhost:15672', 'yellow');
const startTime = Date.now();
const promises = [];
for (let i = 1; i <= 10; i++) {
promises.push(
fetch(`${ADAPTER_URL}/api/routes/optimize`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
packageId: `PKG-LOAD-${i.toString().padStart(3, '0')}`,
address: `${i * 100} Load Test Avenue, Kandy`,
priority: i % 3 === 0 ? 'urgent' : 'normal'
})
})
);
}
const results = await Promise.all(promises);
const endTime = Date.now();
log(`\n✅ All 10 requests completed in ${endTime - startTime}ms`, 'green');
const successful = results.filter(r => r.ok).length;
log(`📊 Success rate: ${successful}/10`, 'yellow');
log('\n💡 Key Observation:', 'cyan');
log(' - All requests went through the queue');
log(' - Worker processed them one by one (prefetch=1)');
log(' - No request was lost!');
log(' - Try starting a 2nd worker to see parallel processing!');
}
/**
* Scenario 3: Request → Get → Update Flow
*/
async function scenario3() {
log('\n═══════════════════════════════════════════════════', 'bright');
log('SCENARIO 3: Complete CRUD Flow', 'cyan');
log('═══════════════════════════════════════════════════', 'bright');
// Create
log('\n📤 Step 1: Create route...', 'blue');
const createResponse = await fetch(`${ADAPTER_URL}/api/routes/optimize`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
packageId: 'PKG-CRUD-001',
address: '789 CRUD Boulevard, Galle',
priority: 'normal'
})
});
const createData = await createResponse.json();
const routeId = createData.routeId;
log(`✅ Route created: ${routeId}`, 'green');
await sleep(500);
// Read
log(`\n📤 Step 2: Get route ${routeId}...`, 'blue');
const getResponse = await fetch(`${ADAPTER_URL}/api/routes/${routeId}`);
const getData = await getResponse.json();
log('✅ Route retrieved:', 'green');
console.log(JSON.stringify(getData.route, null, 2));
await sleep(500);
// Update
log(`\n📤 Step 3: Update route status...`, 'blue');
const updateResponse = await fetch(`${ADAPTER_URL}/api/routes/${routeId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
status: 'IN_TRANSIT',
currentLocation: 'Warehouse A'
})
});
const updateData = await updateResponse.json();
log('✅ Route updated:', 'green');
console.log(JSON.stringify(updateData.route, null, 2));
log('\n📊 What happened:', 'yellow');
log(' - 3 different message types sent to RabbitMQ');
log(' - 3 different queues used (route.optimize, route.get, route.update)');
log(' - Worker handled all three types');
log(' - All through message queues!');
}
/**
* Scenario 4: Resilience Test
*/
async function scenario4() {
log('\n═══════════════════════════════════════════════════', 'bright');
log('SCENARIO 4: Resilience Test', 'cyan');
log('═══════════════════════════════════════════════════', 'bright');
log('\n🔧 Testing message persistence...', 'blue');
log('\n⚠️ Manual Test Required:', 'yellow');
log(' 1. Keep this script running');
log(' 2. Stop the ROS Worker (Ctrl+C in Terminal 4)');
log(' 3. Watch this request hang (waiting for worker)');
log(' 4. Restart the worker');
log(' 5. Watch the request complete!');
log('\n💡 This proves messages survive worker crashes!', 'cyan');
log('\nPress Ctrl+C to skip, or wait 30 seconds for timeout...\n');
try {
const response = await fetch(`${ADAPTER_URL}/api/routes/optimize`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
packageId: 'PKG-RESILIENCE-001',
address: 'Resilience Test Address',
priority: 'normal'
})
});
const data = await response.json();
log('\n✅ Request completed!', 'green');
console.log(data);
} catch (error) {
log('\n⏱️ Request timed out (expected if worker is stopped)', 'yellow');
}
}
/**
* Run All Scenarios
*/
async function runAll() {
console.clear();
log('╔════════════════════════════════════════════════════════╗', 'bright');
log('║ ║', 'bright');
log('║ 🚀 MIDDLEWARE EXPLORATION SCENARIOS 🚀 ║', 'bright');
log('║ ║', 'bright');
log('╚════════════════════════════════════════════════════════╝', 'bright');
log('\n📋 Prerequisites:', 'cyan');
log(' ✓ RabbitMQ running (docker-compose up -d)');
log(' ✓ Mock ROS running (port 4002)');
log(' ✓ REST Adapter running (port 3001)');
log(' ✓ ROS Worker running');
log('\n🎯 What to watch:', 'cyan');
log(' • Terminal output from adapter and worker');
log(' • RabbitMQ dashboard (http://localhost:15672)');
log(' • Message flow and queue depth');
await sleep(3000);
try {
await scenario1();
await sleep(2000);
await scenario2();
await sleep(2000);
await scenario3();
await sleep(2000);
log('\n╔════════════════════════════════════════════════════════╗', 'bright');
log('║ 🎉 Tests Complete! 🎉 ║', 'bright');
log('╚════════════════════════════════════════════════════════╝', 'bright');
log('\n💡 Next Steps:', 'cyan');
log(' 1. Check RabbitMQ dashboard for stats');
log(' 2. Try starting a 2nd worker for parallel processing');
log(' 3. Run scenario 4 manually for resilience testing');
log('\n📚 What you learned:', 'yellow');
log(' ✓ Messages flow through RabbitMQ queues');
log(' ✓ Workers process messages asynchronously');
log(' ✓ System handles load gracefully');
log(' ✓ Request/Reply pattern works perfectly');
log(' ✓ Your middleware is PRODUCTION-READY! 🚀');
} catch (error) {
log(`\n❌ Error: ${error.message}`, 'yellow');
log('\n💡 Make sure all services are running!', 'cyan');
}
}
// Run!
runAll();