nodejs-task-scheduler 1.0.9 โ 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +5 -1
- package/MULTINODE-TEST.md +166 -0
- package/dist/utils/load-balancer.d.ts.map +1 -1
- package/dist/utils/load-balancer.js +4 -0
- package/dist/utils/load-balancer.js.map +1 -1
- package/dist/utils/master-election.d.ts +2 -0
- package/dist/utils/master-election.d.ts.map +1 -1
- package/dist/utils/master-election.js +92 -25
- package/dist/utils/master-election.js.map +1 -1
- package/dist/utils/rabbitmq.d.ts.map +1 -1
- package/dist/utils/rabbitmq.js +17 -3
- package/dist/utils/rabbitmq.js.map +1 -1
- package/docker-rabbitmq.sh +37 -0
- package/package.json +1 -1
- package/run-multinode-test.sh +32 -0
- package/test-multinode.ts +256 -0
- package/test-quick-election.ts +104 -0
- package/test-simple-election.ts +125 -0
- package/test-simple-multinode.ts +94 -0
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
"Bash(npm test:*)",
|
|
15
15
|
"Bash(node:*)",
|
|
16
16
|
"Bash(touch:*)",
|
|
17
|
-
"Bash(npx tsc:*)"
|
|
17
|
+
"Bash(npx tsc:*)",
|
|
18
|
+
"Bash(export RABBITMQ_URL=\"amqp://admin:password@localhost:5672\")",
|
|
19
|
+
"Bash(timeout 60 npx ts-node test-multinode.ts)",
|
|
20
|
+
"Bash(timeout 60 npx ts-node test-simple-election.ts)",
|
|
21
|
+
"Bash(timeout 45 npx ts-node test-quick-election.ts)"
|
|
18
22
|
],
|
|
19
23
|
"deny": []
|
|
20
24
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Multi-Node Master Election Testing
|
|
2
|
+
|
|
3
|
+
This directory contains tests to verify the master election functionality works correctly across multiple nodes using the `njs_testing_` prefix.
|
|
4
|
+
|
|
5
|
+
## Test Files
|
|
6
|
+
|
|
7
|
+
- `test-quick-election.ts` - **Recommended** - Fast test with clean output
|
|
8
|
+
- `test-simple-election.ts` - Detailed test with full output
|
|
9
|
+
- `test-multinode.ts` - Comprehensive automated multi-node test
|
|
10
|
+
- `test-simple-multinode.ts` - Simple test for manual verification
|
|
11
|
+
- `run-multinode-test.sh` - Shell script to run automated tests
|
|
12
|
+
|
|
13
|
+
## Prerequisites
|
|
14
|
+
|
|
15
|
+
1. **RabbitMQ Server Running**
|
|
16
|
+
```bash
|
|
17
|
+
# Using Docker
|
|
18
|
+
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
|
|
19
|
+
|
|
20
|
+
# Or start existing RabbitMQ service
|
|
21
|
+
brew services start rabbitmq # macOS
|
|
22
|
+
sudo systemctl start rabbitmq-server # Linux
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. **Project Built**
|
|
26
|
+
```bash
|
|
27
|
+
npm run build
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Running Tests
|
|
31
|
+
|
|
32
|
+
### Quick Test (Recommended)
|
|
33
|
+
|
|
34
|
+
Run the fast, clean test with minimal output:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Start RabbitMQ (if not running)
|
|
38
|
+
./docker-rabbitmq.sh
|
|
39
|
+
|
|
40
|
+
# Run quick test
|
|
41
|
+
export RABBITMQ_URL="amqp://admin:password@localhost:5672"
|
|
42
|
+
npx ts-node test-quick-election.ts
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Automated Test Suite
|
|
46
|
+
|
|
47
|
+
Run the comprehensive automated test:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Make script executable (Linux/macOS)
|
|
51
|
+
chmod +x run-multinode-test.sh
|
|
52
|
+
|
|
53
|
+
# Run the test
|
|
54
|
+
./run-multinode-test.sh
|
|
55
|
+
|
|
56
|
+
# Or run directly with ts-node
|
|
57
|
+
npx ts-node test-multinode.ts
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**What the automated test does:**
|
|
61
|
+
1. Starts 3 nodes with `njs_testing_` prefix
|
|
62
|
+
2. Verifies single leader election
|
|
63
|
+
3. Tests job scheduling and distribution
|
|
64
|
+
4. Tests leader failover (shuts down leader)
|
|
65
|
+
5. Verifies new leader election
|
|
66
|
+
6. Tests job distribution across remaining nodes
|
|
67
|
+
7. Cleans up all resources
|
|
68
|
+
|
|
69
|
+
### Manual Testing
|
|
70
|
+
|
|
71
|
+
For manual verification, run nodes in separate terminals:
|
|
72
|
+
|
|
73
|
+
**Terminal 1 (Leader + Scheduler):**
|
|
74
|
+
```bash
|
|
75
|
+
npx ts-node test-simple-multinode.ts node1 scheduler
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Terminal 2 (Worker):**
|
|
79
|
+
```bash
|
|
80
|
+
npx ts-node test-simple-multinode.ts node2
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Terminal 3 (Worker):**
|
|
84
|
+
```bash
|
|
85
|
+
npx ts-node test-simple-multinode.ts node3
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**What you should see:**
|
|
89
|
+
- One node becomes leader (๐ LEADER)
|
|
90
|
+
- Other nodes become followers (๐ฅ FOLLOWER)
|
|
91
|
+
- Jobs scheduled by node1 are processed by any available node
|
|
92
|
+
- Status updates every 10 seconds
|
|
93
|
+
- Jobs scheduled every 15 seconds
|
|
94
|
+
|
|
95
|
+
### Testing Leader Failover
|
|
96
|
+
|
|
97
|
+
1. Start multiple nodes as shown above
|
|
98
|
+
2. Note which node is the leader
|
|
99
|
+
3. Stop the leader node (Ctrl+C)
|
|
100
|
+
4. Watch other nodes - one should become the new leader
|
|
101
|
+
5. Jobs should continue processing normally
|
|
102
|
+
|
|
103
|
+
## Expected Behavior
|
|
104
|
+
|
|
105
|
+
### โ
Correct Behavior
|
|
106
|
+
- Only one leader at any time
|
|
107
|
+
- All nodes can process jobs from the queue
|
|
108
|
+
- Leader failover happens automatically
|
|
109
|
+
- Jobs are distributed across available nodes
|
|
110
|
+
- Queues use `njs_testing_` prefix
|
|
111
|
+
|
|
112
|
+
### โ Issues to Watch For
|
|
113
|
+
- Multiple leaders elected simultaneously
|
|
114
|
+
- Split-brain scenarios
|
|
115
|
+
- Connection errors during election
|
|
116
|
+
- Jobs stuck in queue
|
|
117
|
+
- Resource leaks (queues not cleaned up)
|
|
118
|
+
|
|
119
|
+
## Troubleshooting
|
|
120
|
+
|
|
121
|
+
### Connection Errors
|
|
122
|
+
```
|
|
123
|
+
Error: Not connected to RabbitMQ
|
|
124
|
+
```
|
|
125
|
+
- Ensure RabbitMQ is running
|
|
126
|
+
- Check connection URL in environment variable
|
|
127
|
+
- Verify network connectivity
|
|
128
|
+
|
|
129
|
+
### Access Refused Errors
|
|
130
|
+
```
|
|
131
|
+
ACCESS_REFUSED - queue 'njs_testing_leader-election' in exclusive use
|
|
132
|
+
```
|
|
133
|
+
- This is expected when multiple nodes compete for leadership
|
|
134
|
+
- Should resolve automatically with follower election
|
|
135
|
+
|
|
136
|
+
### No Leader Elected
|
|
137
|
+
- Check RabbitMQ server is accessible
|
|
138
|
+
- Verify queue permissions
|
|
139
|
+
- Look for connection timeouts
|
|
140
|
+
|
|
141
|
+
## Cleanup
|
|
142
|
+
|
|
143
|
+
The tests automatically clean up their resources, but if needed, you can manually clean up:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Connect to RabbitMQ management
|
|
147
|
+
http://localhost:15672
|
|
148
|
+
|
|
149
|
+
# Delete queues with njs_testing_ prefix
|
|
150
|
+
# Or use rabbitmqctl:
|
|
151
|
+
sudo rabbitmqctl list_queues | grep njs_testing
|
|
152
|
+
sudo rabbitmqctl delete_queue njs_testing_leader-election
|
|
153
|
+
sudo rabbitmqctl delete_queue njs_testing_leader-heartbeat
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Environment Variables
|
|
157
|
+
|
|
158
|
+
- `RABBITMQ_URL` - RabbitMQ connection URL (default: `amqp://localhost:5672`)
|
|
159
|
+
|
|
160
|
+
## Test Results
|
|
161
|
+
|
|
162
|
+
When tests pass, you should see:
|
|
163
|
+
- โ
Single leader elected
|
|
164
|
+
- โ
Jobs scheduled successfully
|
|
165
|
+
- โ
Leader failover completed successfully
|
|
166
|
+
- โ
All multi-node tests completed successfully!
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-balancer.d.ts","sourceRoot":"","sources":["../../src/utils/load-balancer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,aAAa,CAAS;gBAElB,UAAU,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM;IAKpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrB,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5E,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAiBpD,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAetD,WAAW,IAAI,QAAQ,EAAE;IAIzB,cAAc,IAAI,QAAQ,EAAE;IAK5B,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;YAc5C,oBAAoB;YAapB,cAAc;YAQd,aAAa;YAgBb,oBAAoB;
|
|
1
|
+
{"version":3,"file":"load-balancer.d.ts","sourceRoot":"","sources":["../../src/utils/load-balancer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,aAAa,CAAS;gBAElB,UAAU,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM;IAKpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrB,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5E,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAiBpD,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAetD,WAAW,IAAI,QAAQ,EAAE;IAIzB,cAAc,IAAI,QAAQ,EAAE;IAK5B,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;YAc5C,oBAAoB;YAapB,cAAc;YAQd,aAAa;YAgBb,oBAAoB;YAqBpB,mBAAmB;IAgBjC,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,gBAAgB;CAYzB"}
|
|
@@ -102,6 +102,10 @@ class LoadBalancer {
|
|
|
102
102
|
await channel.publish('heartbeat', '', Buffer.from(JSON.stringify(heartbeat)));
|
|
103
103
|
}
|
|
104
104
|
async sendOfflineHeartbeat() {
|
|
105
|
+
if (!this.connection.isConnected()) {
|
|
106
|
+
// Silently skip offline heartbeat when not connected - this is expected during shutdown
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
105
109
|
const channel = this.connection.getChannel();
|
|
106
110
|
const heartbeat = {
|
|
107
111
|
nodeId: this.nodeId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-balancer.js","sourceRoot":"","sources":["../../src/utils/load-balancer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"load-balancer.js","sourceRoot":"","sources":["../../src/utils/load-balancer.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,7 @@ export declare class MasterElection extends EventEmitter {
|
|
|
31
31
|
private heartbeatQueue;
|
|
32
32
|
private lastHeartbeat?;
|
|
33
33
|
private isRunning;
|
|
34
|
+
private consumerTag?;
|
|
34
35
|
constructor(config: MasterElectionConfig);
|
|
35
36
|
start(): Promise<void>;
|
|
36
37
|
stop(): Promise<void>;
|
|
@@ -48,6 +49,7 @@ export declare class MasterElection extends EventEmitter {
|
|
|
48
49
|
private resignLeadership;
|
|
49
50
|
private startPeriodicCleanup;
|
|
50
51
|
private cleanupHeartbeatQueue;
|
|
52
|
+
private waitForConnection;
|
|
51
53
|
private getQueueName;
|
|
52
54
|
}
|
|
53
55
|
//# sourceMappingURL=master-election.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-election.d.ts","sourceRoot":"","sources":["../../src/utils/master-election.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,oBAAY,eAAe;IACzB,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAO;IAC7B,OAAO,CAAC,SAAS,CAAS;
|
|
1
|
+
{"version":3,"file":"master-election.d.ts","sourceRoot":"","sources":["../../src/utils/master-election.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,oBAAY,eAAe;IACzB,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAO;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAC,CAAS;gBAEjB,MAAM,EAAE,oBAAoB;IAYlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAetB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA6B3B,QAAQ,IAAI,OAAO;IAInB,SAAS,IAAI,MAAM;IAInB,QAAQ,IAAI,eAAe;YAIb,gBAAgB;YAmChB,aAAa;YAYb,iBAAiB;YAgCjB,YAAY;YAoBZ,cAAc;YAuBd,aAAa;YA2Cb,sBAAsB;IAkFpC,OAAO,CAAC,sBAAsB;YAahB,gBAAgB;IA0B9B,OAAO,CAAC,oBAAoB;YAwBd,qBAAqB;YAoBrB,iBAAiB;IAe/B,OAAO,CAAC,YAAY;CAGrB"}
|
|
@@ -27,6 +27,8 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
this.isRunning = true;
|
|
30
|
+
// Wait for connection to be established
|
|
31
|
+
await this.waitForConnection();
|
|
30
32
|
await this.initializeQueues();
|
|
31
33
|
this.startPeriodicCleanup();
|
|
32
34
|
await this.startElection();
|
|
@@ -62,6 +64,9 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
62
64
|
return this.state;
|
|
63
65
|
}
|
|
64
66
|
async initializeQueues() {
|
|
67
|
+
if (!this.connection.isConnected()) {
|
|
68
|
+
throw new Error('Not connected to RabbitMQ');
|
|
69
|
+
}
|
|
65
70
|
const channel = this.connection.getChannel();
|
|
66
71
|
// Election queue - exclusive, auto-delete when connection closes
|
|
67
72
|
await channel.assertQueue(this.electionQueue, {
|
|
@@ -99,6 +104,9 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
async attemptLeadership() {
|
|
107
|
+
if (!this.connection.isConnected()) {
|
|
108
|
+
throw new Error('Not connected to RabbitMQ');
|
|
109
|
+
}
|
|
102
110
|
const channel = this.connection.getChannel();
|
|
103
111
|
try {
|
|
104
112
|
// Try to consume from election queue exclusively
|
|
@@ -108,12 +116,13 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
108
116
|
noAck: true
|
|
109
117
|
});
|
|
110
118
|
if (consumerResult) {
|
|
119
|
+
this.consumerTag = consumerResult.consumerTag;
|
|
111
120
|
await this.becomeLeader();
|
|
112
121
|
}
|
|
113
122
|
}
|
|
114
123
|
catch (error) {
|
|
115
124
|
if (error.message && (error.message.includes('exclusive') || error.code === 403)) {
|
|
116
|
-
// Another node is already the leader
|
|
125
|
+
// Another node is already the leader - this is expected behavior
|
|
117
126
|
await this.becomeFollower();
|
|
118
127
|
}
|
|
119
128
|
else {
|
|
@@ -162,6 +171,9 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
162
171
|
return;
|
|
163
172
|
}
|
|
164
173
|
try {
|
|
174
|
+
if (!this.connection.isConnected()) {
|
|
175
|
+
throw new Error('Not connected to RabbitMQ');
|
|
176
|
+
}
|
|
165
177
|
const channel = this.connection.getChannel();
|
|
166
178
|
const heartbeatMessage = {
|
|
167
179
|
nodeId: this.nodeId,
|
|
@@ -191,34 +203,66 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
191
203
|
return;
|
|
192
204
|
}
|
|
193
205
|
try {
|
|
206
|
+
if (!this.connection.isConnected()) {
|
|
207
|
+
throw new Error('Not connected to RabbitMQ');
|
|
208
|
+
}
|
|
194
209
|
const channel = this.connection.getChannel();
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
const heartbeat = JSON.parse(msg.content.toString());
|
|
201
|
-
if (heartbeat.nodeId !== this.nodeId) {
|
|
202
|
-
// Received heartbeat from current leader
|
|
203
|
-
this.lastHeartbeat = new Date(heartbeat.timestamp);
|
|
204
|
-
this.resetLeadershipTimeout();
|
|
210
|
+
try {
|
|
211
|
+
await channel.consume(this.heartbeatQueue, async (msg) => {
|
|
212
|
+
if (!msg || !this.isRunning) {
|
|
213
|
+
return;
|
|
205
214
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
215
|
+
try {
|
|
216
|
+
const heartbeat = JSON.parse(msg.content.toString());
|
|
217
|
+
if (heartbeat.nodeId !== this.nodeId) {
|
|
218
|
+
// Received heartbeat from current leader
|
|
219
|
+
this.lastHeartbeat = new Date(heartbeat.timestamp);
|
|
220
|
+
this.resetLeadershipTimeout();
|
|
221
|
+
}
|
|
222
|
+
channel.ack(msg);
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
console.error('Error processing heartbeat:', error);
|
|
226
|
+
try {
|
|
227
|
+
channel.nack(msg, false, false);
|
|
228
|
+
}
|
|
229
|
+
catch (nackError) {
|
|
230
|
+
// Ignore nack errors during cleanup
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}, { noAck: false });
|
|
234
|
+
}
|
|
235
|
+
catch (consumeError) {
|
|
236
|
+
throw new Error(`Failed to consume heartbeat queue: ${consumeError.message}`);
|
|
237
|
+
}
|
|
213
238
|
// Start timeout to detect leader failure
|
|
214
239
|
this.resetLeadershipTimeout();
|
|
215
240
|
}
|
|
216
241
|
catch (error) {
|
|
217
|
-
|
|
242
|
+
// Suppress expected errors during election and cleanup
|
|
243
|
+
const isExpectedError = error.message && (error.message.includes('NOT_FOUND') ||
|
|
244
|
+
error.message.includes('Not connected to RabbitMQ') ||
|
|
245
|
+
error.message.includes('not connected') ||
|
|
246
|
+
error.code === 404 ||
|
|
247
|
+
error.code === 403);
|
|
248
|
+
if (!isExpectedError) {
|
|
249
|
+
console.error(`Failed to monitor heartbeat for node ${this.nodeId}:`, error.message);
|
|
250
|
+
}
|
|
218
251
|
// If we can't monitor heartbeat, try to start election after a delay
|
|
219
252
|
setTimeout(async () => {
|
|
220
253
|
if (this.isRunning && this.state === LeadershipState.FOLLOWER) {
|
|
221
|
-
|
|
254
|
+
try {
|
|
255
|
+
await this.startElection();
|
|
256
|
+
}
|
|
257
|
+
catch (retryError) {
|
|
258
|
+
const isRetryExpectedError = retryError.message && (retryError.message.includes('NOT_FOUND') ||
|
|
259
|
+
retryError.message.includes('not connected') ||
|
|
260
|
+
retryError.code === 404 ||
|
|
261
|
+
retryError.code === 403);
|
|
262
|
+
if (!isRetryExpectedError) {
|
|
263
|
+
console.error(`Retry election failed for node ${this.nodeId}:`, retryError.message);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
222
266
|
}
|
|
223
267
|
}, this.heartbeatInterval);
|
|
224
268
|
}
|
|
@@ -245,11 +289,14 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
245
289
|
}
|
|
246
290
|
// Cancel exclusive consumption to allow other nodes to become leader
|
|
247
291
|
try {
|
|
248
|
-
|
|
249
|
-
|
|
292
|
+
if (this.consumerTag && this.connection.isConnected()) {
|
|
293
|
+
const channel = this.connection.getChannel();
|
|
294
|
+
await channel.cancel(this.consumerTag);
|
|
295
|
+
this.consumerTag = undefined;
|
|
296
|
+
}
|
|
250
297
|
}
|
|
251
298
|
catch (error) {
|
|
252
|
-
console.warn('Error canceling election queue consumption:', error);
|
|
299
|
+
console.warn('Error canceling election queue consumption:', error.message);
|
|
253
300
|
}
|
|
254
301
|
await this.becomeFollower();
|
|
255
302
|
}
|
|
@@ -258,6 +305,9 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
258
305
|
this.cleanupTimer = setInterval(async () => {
|
|
259
306
|
if (this.isRunning && this.state === LeadershipState.FOLLOWER) {
|
|
260
307
|
try {
|
|
308
|
+
if (!this.connection.isConnected()) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
261
311
|
const channel = this.connection.getChannel();
|
|
262
312
|
// Only purge if queue has too many messages (check queue info)
|
|
263
313
|
const queueInfo = await channel.checkQueue(this.heartbeatQueue);
|
|
@@ -267,13 +317,18 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
267
317
|
}
|
|
268
318
|
}
|
|
269
319
|
catch (error) {
|
|
270
|
-
// Queue might not exist yet, ignore error
|
|
320
|
+
// Queue might not exist yet or connection issues, ignore error
|
|
321
|
+
console.debug(`Cleanup error (ignored): ${error.message}`);
|
|
271
322
|
}
|
|
272
323
|
}
|
|
273
324
|
}, 60000); // Every minute
|
|
274
325
|
}
|
|
275
326
|
async cleanupHeartbeatQueue() {
|
|
276
327
|
try {
|
|
328
|
+
if (!this.connection.isConnected()) {
|
|
329
|
+
// Silently skip cleanup when not connected - this is expected during shutdown
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
277
332
|
const channel = this.connection.getChannel();
|
|
278
333
|
// Purge any remaining messages from heartbeat queue
|
|
279
334
|
await channel.purgeQueue(this.heartbeatQueue);
|
|
@@ -281,7 +336,19 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
281
336
|
await channel.deleteQueue(this.heartbeatQueue, { ifEmpty: true });
|
|
282
337
|
}
|
|
283
338
|
catch (error) {
|
|
284
|
-
console.warn(`Error cleaning up heartbeat queue for node ${this.nodeId}:`, error);
|
|
339
|
+
console.warn(`Error cleaning up heartbeat queue for node ${this.nodeId}:`, error.message);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
async waitForConnection() {
|
|
343
|
+
const maxWaitTime = 30000; // 30 seconds
|
|
344
|
+
const checkInterval = 100; // 100ms
|
|
345
|
+
let waitTime = 0;
|
|
346
|
+
while (!this.connection.isConnected() && waitTime < maxWaitTime) {
|
|
347
|
+
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
348
|
+
waitTime += checkInterval;
|
|
349
|
+
}
|
|
350
|
+
if (!this.connection.isConnected()) {
|
|
351
|
+
throw new Error('Failed to establish RabbitMQ connection within timeout period');
|
|
285
352
|
}
|
|
286
353
|
}
|
|
287
354
|
getQueueName(baseName) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-election.js","sourceRoot":"","sources":["../../src/utils/master-election.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"master-election.js","sourceRoot":"","sources":["../../src/utils/master-election.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq.d.ts","sourceRoot":"","sources":["../../src/utils/rabbitmq.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,oBAAoB,CAAM;IAClC,OAAO,CAAC,cAAc,CAAQ;gBAElB,MAAM,EAAE,gBAAgB;IAI9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBjC,UAAU,IAAI,GAAG;IAOjB,WAAW,IAAI,OAAO;YAIR,qBAAqB;
|
|
1
|
+
{"version":3,"file":"rabbitmq.d.ts","sourceRoot":"","sources":["../../src/utils/rabbitmq.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,oBAAoB,CAAM;IAClC,OAAO,CAAC,cAAc,CAAQ;gBAElB,MAAM,EAAE,gBAAgB;IAI9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBjC,UAAU,IAAI,GAAG;IAOjB,WAAW,IAAI,OAAO;YAIR,qBAAqB;YAiBrB,qBAAqB;YAUrB,eAAe;CAgB9B"}
|
package/dist/utils/rabbitmq.js
CHANGED
|
@@ -90,11 +90,22 @@ class RabbitMQConnection {
|
|
|
90
90
|
return this.connection !== null && this.channel !== null;
|
|
91
91
|
}
|
|
92
92
|
async handleConnectionError(error) {
|
|
93
|
-
|
|
93
|
+
// Suppress expected election and cleanup errors
|
|
94
|
+
const isExpectedError = error.message && (error.message.includes('ACCESS_REFUSED') ||
|
|
95
|
+
error.message.includes('NOT_FOUND') ||
|
|
96
|
+
error.message.includes('exclusive use') ||
|
|
97
|
+
error.message.includes('404') ||
|
|
98
|
+
error.message.includes('403'));
|
|
99
|
+
if (!isExpectedError) {
|
|
100
|
+
console.error('RabbitMQ connection error:', error);
|
|
101
|
+
}
|
|
94
102
|
await this.handleReconnect();
|
|
95
103
|
}
|
|
96
104
|
async handleConnectionClose() {
|
|
97
|
-
|
|
105
|
+
// Only log connection close if it's unexpected (not during shutdown)
|
|
106
|
+
if (this.reconnectAttempts < 2) {
|
|
107
|
+
console.log('RabbitMQ connection closed');
|
|
108
|
+
}
|
|
98
109
|
this.connection = null;
|
|
99
110
|
this.channel = null;
|
|
100
111
|
await this.handleReconnect();
|
|
@@ -105,7 +116,10 @@ class RabbitMQConnection {
|
|
|
105
116
|
return;
|
|
106
117
|
}
|
|
107
118
|
this.reconnectAttempts++;
|
|
108
|
-
|
|
119
|
+
// Only log reconnection attempts if they're taking a while (after attempt 3)
|
|
120
|
+
if (this.reconnectAttempts > 3) {
|
|
121
|
+
console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
|
|
122
|
+
}
|
|
109
123
|
await new Promise(resolve => setTimeout(resolve, this.reconnectDelay));
|
|
110
124
|
await this.connect();
|
|
111
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq.js","sourceRoot":"","sources":["../../src/utils/rabbitmq.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8CAAgC;AAGhC,MAAa,kBAAkB;IAQ7B,YAAY,MAAwB;QAP5B,eAAU,GAAQ,IAAI,CAAC;QACvB,YAAO,GAAQ,IAAI,CAAC;QAEpB,sBAAiB,GAAG,CAAC,CAAC;QACtB,yBAAoB,GAAG,EAAE,CAAC;QAC1B,mBAAc,GAAG,IAAI,CAAC;QAG5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC;YACH,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC3E,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;YAErD,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACnE,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAEnE,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;YACvD,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;YAC9C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;QAED,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;gBAC9B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACzB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;YACjD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;IACH,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,UAAU,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;IAC3D,CAAC;IAEO,KAAK,CAAC,qBAAqB,CAAC,KAAY;QAC9C,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"rabbitmq.js","sourceRoot":"","sources":["../../src/utils/rabbitmq.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# RabbitMQ Docker setup for testing
|
|
4
|
+
# This script starts RabbitMQ with management interface for local testing
|
|
5
|
+
|
|
6
|
+
echo "๐ฐ Starting RabbitMQ with Docker for testing..."
|
|
7
|
+
|
|
8
|
+
# Stop and remove existing container if it exists
|
|
9
|
+
docker stop rabbitmq-test 2>/dev/null || true
|
|
10
|
+
docker rm rabbitmq-test 2>/dev/null || true
|
|
11
|
+
|
|
12
|
+
# Start RabbitMQ with management plugin
|
|
13
|
+
docker run -d \
|
|
14
|
+
--name rabbitmq-test \
|
|
15
|
+
-p 5672:5672 \
|
|
16
|
+
-p 15672:15672 \
|
|
17
|
+
-e RABBITMQ_DEFAULT_USER=admin \
|
|
18
|
+
-e RABBITMQ_DEFAULT_PASS=password \
|
|
19
|
+
rabbitmq:3-management
|
|
20
|
+
|
|
21
|
+
echo "โณ Waiting for RabbitMQ to start..."
|
|
22
|
+
sleep 10
|
|
23
|
+
|
|
24
|
+
# Check if RabbitMQ is ready
|
|
25
|
+
if curl -f http://localhost:15672/api/overview &>/dev/null; then
|
|
26
|
+
echo "โ
RabbitMQ is running!"
|
|
27
|
+
echo ""
|
|
28
|
+
echo "๐ Management UI: http://localhost:15672"
|
|
29
|
+
echo "๐ค Username: admin"
|
|
30
|
+
echo "๐ Password: password"
|
|
31
|
+
echo "๐ Connection URL: amqp://admin:password@localhost:5672"
|
|
32
|
+
echo ""
|
|
33
|
+
echo "๐งช Ready for multi-node testing!"
|
|
34
|
+
else
|
|
35
|
+
echo "โ RabbitMQ failed to start properly"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
package/package.json
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Multi-node test runner script
|
|
4
|
+
# This script runs the multi-node test with proper environment setup
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "๐ Multi-Node Master Election Test Runner"
|
|
9
|
+
echo "========================================"
|
|
10
|
+
|
|
11
|
+
# Check if RabbitMQ is running
|
|
12
|
+
echo "๐ก Checking RabbitMQ connection..."
|
|
13
|
+
if ! curl -f http://localhost:15672/api/overview &>/dev/null; then
|
|
14
|
+
echo "โ RabbitMQ management interface not accessible at localhost:15672"
|
|
15
|
+
echo "Please ensure RabbitMQ is running with management plugin enabled"
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Set default RabbitMQ URL if not provided
|
|
20
|
+
export RABBITMQ_URL=${RABBITMQ_URL:-"amqp://admin:password@localhost:5672"}
|
|
21
|
+
|
|
22
|
+
echo "๐ Using RabbitMQ URL: $RABBITMQ_URL"
|
|
23
|
+
|
|
24
|
+
# Build the project first
|
|
25
|
+
echo "๐จ Building project..."
|
|
26
|
+
npm run build
|
|
27
|
+
|
|
28
|
+
# Run the multi-node test
|
|
29
|
+
echo "๐งช Starting multi-node test..."
|
|
30
|
+
npx ts-node test-multinode.ts
|
|
31
|
+
|
|
32
|
+
echo "โ
Multi-node test completed!"
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
import { TaskScheduler } from './src';
|
|
4
|
+
|
|
5
|
+
interface NodeTestConfig {
|
|
6
|
+
nodeId: string;
|
|
7
|
+
port: number;
|
|
8
|
+
isLeaderExpected?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class MultiNodeTester {
|
|
12
|
+
private nodes: Map<string, TaskScheduler> = new Map();
|
|
13
|
+
private nodeConfigs: NodeTestConfig[] = [
|
|
14
|
+
{ nodeId: 'node-1', port: 3001, isLeaderExpected: true },
|
|
15
|
+
{ nodeId: 'node-2', port: 3002 },
|
|
16
|
+
{ nodeId: 'node-3', port: 3003 }
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
async runTest(): Promise<void> {
|
|
20
|
+
console.log('๐ Starting multi-node master election test with prefix: njs_testing_');
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// Start all nodes
|
|
24
|
+
await this.startAllNodes();
|
|
25
|
+
|
|
26
|
+
// Wait for election to stabilize
|
|
27
|
+
console.log('โณ Waiting for master election to stabilize...');
|
|
28
|
+
await this.sleep(5000);
|
|
29
|
+
|
|
30
|
+
// Check initial leader
|
|
31
|
+
await this.checkLeaderStatus();
|
|
32
|
+
|
|
33
|
+
// Test basic job scheduling
|
|
34
|
+
await this.testJobScheduling();
|
|
35
|
+
|
|
36
|
+
console.log('โณ Waiting for jobs to process...');
|
|
37
|
+
await this.sleep(8000);
|
|
38
|
+
|
|
39
|
+
// Test leader failover (simplified)
|
|
40
|
+
await this.testLeaderFailover();
|
|
41
|
+
|
|
42
|
+
console.log('โ
All multi-node tests completed successfully!');
|
|
43
|
+
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error('โ Multi-node test failed:', error);
|
|
46
|
+
} finally {
|
|
47
|
+
await this.cleanup();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private async startAllNodes(): Promise<void> {
|
|
52
|
+
console.log('๐ก Starting nodes...');
|
|
53
|
+
|
|
54
|
+
for (const config of this.nodeConfigs) {
|
|
55
|
+
console.log(`Starting ${config.nodeId}...`);
|
|
56
|
+
const scheduler = new TaskScheduler({
|
|
57
|
+
url: process.env.RABBITMQ_URL || 'amqp://admin:password@localhost:5672',
|
|
58
|
+
queuePrefix: 'njs_testing_'
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await scheduler.initialize();
|
|
62
|
+
|
|
63
|
+
// Wait a bit for full initialization
|
|
64
|
+
await this.sleep(2000);
|
|
65
|
+
|
|
66
|
+
this.nodes.set(config.nodeId, scheduler);
|
|
67
|
+
|
|
68
|
+
// Create a worker on each node
|
|
69
|
+
await scheduler.createWorker({
|
|
70
|
+
name: `${config.nodeId}-worker`,
|
|
71
|
+
concurrency: 2,
|
|
72
|
+
queues: ['test-jobs'],
|
|
73
|
+
handlers: {
|
|
74
|
+
'test-job': async (data: any) => {
|
|
75
|
+
console.log(`๐ ${config.nodeId} processing job:`, data.jobId);
|
|
76
|
+
await this.sleep(1000); // Simulate work
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
processedBy: config.nodeId,
|
|
80
|
+
timestamp: new Date()
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
'priority-job': async (data: any) => {
|
|
84
|
+
console.log(`โญ ${config.nodeId} processing priority job:`, data.jobId);
|
|
85
|
+
return {
|
|
86
|
+
success: true,
|
|
87
|
+
processedBy: config.nodeId,
|
|
88
|
+
priority: true
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
console.log(`โ
${config.nodeId} started and ready`);
|
|
95
|
+
|
|
96
|
+
// Stagger node startup to avoid race conditions
|
|
97
|
+
await this.sleep(1000);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private async checkLeaderStatus(): Promise<void> {
|
|
102
|
+
console.log('\n๐ Checking leader election status...');
|
|
103
|
+
|
|
104
|
+
let leaderCount = 0;
|
|
105
|
+
let leaderNode = '';
|
|
106
|
+
|
|
107
|
+
for (const [nodeId, scheduler] of this.nodes) {
|
|
108
|
+
const nodeInfo = await scheduler.getNodeInfo();
|
|
109
|
+
// @ts-ignore
|
|
110
|
+
const isLeader = nodeInfo.isLeader;
|
|
111
|
+
|
|
112
|
+
console.log(`${nodeId}: ${isLeader ? '๐ LEADER' : '๐ฅ FOLLOWER'} (Node ID: ${nodeInfo.nodeId})`);
|
|
113
|
+
|
|
114
|
+
if (isLeader) {
|
|
115
|
+
leaderCount++;
|
|
116
|
+
leaderNode = nodeId;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (leaderCount === 0) {
|
|
121
|
+
throw new Error('No leader elected!');
|
|
122
|
+
} else if (leaderCount > 1) {
|
|
123
|
+
throw new Error(`Multiple leaders detected: ${leaderCount}`);
|
|
124
|
+
} else {
|
|
125
|
+
console.log(`โ
Single leader elected: ${leaderNode}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private async testJobScheduling(): Promise<void> {
|
|
130
|
+
console.log('\n๐ Testing job scheduling...');
|
|
131
|
+
|
|
132
|
+
// Get any scheduler to schedule jobs (should work from any node)
|
|
133
|
+
const scheduler = this.nodes.values().next().value;
|
|
134
|
+
|
|
135
|
+
// Schedule a few test jobs
|
|
136
|
+
for (let i = 1; i <= 3; i++) {
|
|
137
|
+
try {
|
|
138
|
+
await scheduler.scheduleJob({
|
|
139
|
+
id: `test-job-${i}`,
|
|
140
|
+
name: `Test Job ${i}`,
|
|
141
|
+
handler: 'test-job',
|
|
142
|
+
data: { jobId: `test-job-${i}`, message: `Hello from job ${i}` }
|
|
143
|
+
});
|
|
144
|
+
console.log(`โ
Job ${i} scheduled`);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(`โ Failed to schedule job ${i}:`, error.message);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private async testLeaderFailover(): Promise<void> {
|
|
152
|
+
console.log('\n๐ Testing leader failover...');
|
|
153
|
+
|
|
154
|
+
// Find current leader
|
|
155
|
+
let currentLeader = '';
|
|
156
|
+
for (const [nodeId, scheduler] of this.nodes) {
|
|
157
|
+
const nodeInfo = await scheduler.getNodeInfo();
|
|
158
|
+
// @ts-ignore
|
|
159
|
+
if (nodeInfo.isLeader) {
|
|
160
|
+
currentLeader = nodeId;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!currentLeader) {
|
|
166
|
+
throw new Error('No leader found for failover test');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
console.log(`๐ Shutting down current leader: ${currentLeader}`);
|
|
170
|
+
|
|
171
|
+
// Shutdown the leader
|
|
172
|
+
const leaderScheduler = this.nodes.get(currentLeader)!;
|
|
173
|
+
await leaderScheduler.shutdown();
|
|
174
|
+
this.nodes.delete(currentLeader);
|
|
175
|
+
|
|
176
|
+
// Wait for new election
|
|
177
|
+
console.log('โณ Waiting for new leader election...');
|
|
178
|
+
await this.sleep(8000);
|
|
179
|
+
|
|
180
|
+
// Check new leader
|
|
181
|
+
await this.checkLeaderStatus();
|
|
182
|
+
|
|
183
|
+
console.log('โ
Leader failover completed successfully');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private async testJobDistribution(): Promise<void> {
|
|
187
|
+
console.log('\nโ๏ธ Testing job distribution across remaining nodes...');
|
|
188
|
+
|
|
189
|
+
// Get any remaining scheduler
|
|
190
|
+
const scheduler = this.nodes.values().next().value;
|
|
191
|
+
|
|
192
|
+
// Schedule jobs that should be distributed
|
|
193
|
+
const jobPromises = [];
|
|
194
|
+
for (let i = 1; i <= 6; i++) {
|
|
195
|
+
const jobPromise = scheduler.scheduleJob({
|
|
196
|
+
id: `distributed-job-${i}`,
|
|
197
|
+
name: `Distributed Job ${i}`,
|
|
198
|
+
handler: 'test-job',
|
|
199
|
+
data: { jobId: `distributed-job-${i}`, message: `Distributed job ${i}` }
|
|
200
|
+
});
|
|
201
|
+
jobPromises.push(jobPromise);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
await Promise.all(jobPromises);
|
|
205
|
+
console.log('โ
Distributed jobs scheduled');
|
|
206
|
+
|
|
207
|
+
// Wait for processing
|
|
208
|
+
await this.sleep(10000);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private async cleanup(): Promise<void> {
|
|
212
|
+
console.log('\n๐งน Cleaning up test resources...');
|
|
213
|
+
|
|
214
|
+
for (const [nodeId, scheduler] of this.nodes) {
|
|
215
|
+
try {
|
|
216
|
+
console.log(`Shutting down ${nodeId}...`);
|
|
217
|
+
await scheduler.shutdown();
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.warn(`Warning: Error shutting down ${nodeId}:`, error.message || error);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
this.nodes.clear();
|
|
224
|
+
|
|
225
|
+
// Give time for cleanup
|
|
226
|
+
await this.sleep(2000);
|
|
227
|
+
|
|
228
|
+
console.log('โ
Cleanup completed');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private sleep(ms: number): Promise<void> {
|
|
232
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Handle graceful shutdown
|
|
237
|
+
process.on('SIGINT', () => {
|
|
238
|
+
console.log('\n๐ Received SIGINT, shutting down test...');
|
|
239
|
+
process.exit(0);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
process.on('SIGTERM', () => {
|
|
243
|
+
console.log('\n๐ Received SIGTERM, shutting down test...');
|
|
244
|
+
process.exit(0);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Run the test
|
|
248
|
+
if (require.main === module) {
|
|
249
|
+
const tester = new MultiNodeTester();
|
|
250
|
+
tester.runTest().catch(error => {
|
|
251
|
+
console.error('โ Test execution failed:', error);
|
|
252
|
+
process.exit(1);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export { MultiNodeTester };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
// Quick test to verify master election works with minimal output
|
|
4
|
+
import { TaskScheduler } from './src';
|
|
5
|
+
|
|
6
|
+
async function quickElectionTest() {
|
|
7
|
+
console.log('๐ Quick master election test (njs_testing_ prefix)');
|
|
8
|
+
|
|
9
|
+
const nodes = [];
|
|
10
|
+
let testsPassed = 0;
|
|
11
|
+
const totalTests = 2;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
// Test 1: Single leader election
|
|
15
|
+
console.log('\n๐ Test 1: Single leader election');
|
|
16
|
+
|
|
17
|
+
const node1 = new TaskScheduler({
|
|
18
|
+
url: process.env.RABBITMQ_URL || 'amqp://admin:password@localhost:5672',
|
|
19
|
+
queuePrefix: 'njs_testing_'
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const node2 = new TaskScheduler({
|
|
23
|
+
url: process.env.RABBITMQ_URL || 'amqp://admin:password@localhost:5672',
|
|
24
|
+
queuePrefix: 'njs_testing_'
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
await node1.initialize();
|
|
28
|
+
await node2.initialize();
|
|
29
|
+
|
|
30
|
+
nodes.push({ id: 'node1', scheduler: node1 });
|
|
31
|
+
nodes.push({ id: 'node2', scheduler: node2 });
|
|
32
|
+
|
|
33
|
+
// Wait for election
|
|
34
|
+
await sleep(6000);
|
|
35
|
+
|
|
36
|
+
const node1IsLeader = node1.isLeader();
|
|
37
|
+
const node2IsLeader = node2.isLeader();
|
|
38
|
+
const leaderCount = (node1IsLeader ? 1 : 0) + (node2IsLeader ? 1 : 0);
|
|
39
|
+
|
|
40
|
+
if (leaderCount === 1) {
|
|
41
|
+
console.log('โ
Test 1 PASSED: Exactly one leader elected');
|
|
42
|
+
testsPassed++;
|
|
43
|
+
} else {
|
|
44
|
+
console.log(`โ Test 1 FAILED: ${leaderCount} leaders found`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Test 2: Leader failover
|
|
48
|
+
console.log('\n๐ Test 2: Leader failover');
|
|
49
|
+
|
|
50
|
+
const currentLeader = node1IsLeader ? nodes[0] : nodes[1];
|
|
51
|
+
const follower = node1IsLeader ? nodes[1] : nodes[0];
|
|
52
|
+
|
|
53
|
+
// Shutdown leader
|
|
54
|
+
await currentLeader.scheduler.shutdown();
|
|
55
|
+
nodes.splice(nodes.indexOf(currentLeader), 1);
|
|
56
|
+
|
|
57
|
+
// Wait for failover
|
|
58
|
+
await sleep(6000);
|
|
59
|
+
|
|
60
|
+
const newLeaderIsLeader = follower.scheduler.isLeader();
|
|
61
|
+
|
|
62
|
+
if (newLeaderIsLeader) {
|
|
63
|
+
console.log('โ
Test 2 PASSED: Failover successful');
|
|
64
|
+
testsPassed++;
|
|
65
|
+
} else {
|
|
66
|
+
console.log('โ Test 2 FAILED: Failover failed');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Summary
|
|
70
|
+
console.log(`\n๐ Test Results: ${testsPassed}/${totalTests} tests passed`);
|
|
71
|
+
|
|
72
|
+
if (testsPassed === totalTests) {
|
|
73
|
+
console.log('๐ ALL TESTS PASSED! Master election is working correctly.');
|
|
74
|
+
console.log('โ
njs_testing_ prefix multinode test SUCCESSFUL');
|
|
75
|
+
} else {
|
|
76
|
+
console.log('โ Some tests failed. Check master election implementation.');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('โ Test execution failed:', error.message);
|
|
81
|
+
} finally {
|
|
82
|
+
// Quick cleanup
|
|
83
|
+
for (const node of nodes) {
|
|
84
|
+
try {
|
|
85
|
+
await node.scheduler.shutdown();
|
|
86
|
+
} catch (error) {
|
|
87
|
+
// Ignore cleanup errors
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Force exit
|
|
92
|
+
setTimeout(() => process.exit(testsPassed === totalTests ? 0 : 1), 1000);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function sleep(ms: number): Promise<void> {
|
|
97
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Suppress error logs during cleanup
|
|
101
|
+
process.on('uncaughtException', () => {});
|
|
102
|
+
process.on('unhandledRejection', () => {});
|
|
103
|
+
|
|
104
|
+
quickElectionTest();
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
// Simplified test to verify master election works
|
|
4
|
+
import { TaskScheduler } from './src';
|
|
5
|
+
|
|
6
|
+
async function testBasicElection() {
|
|
7
|
+
console.log('๐ Testing basic master election with njs_testing_ prefix');
|
|
8
|
+
|
|
9
|
+
const nodes = [];
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
// Start first node
|
|
13
|
+
console.log('Starting node 1...');
|
|
14
|
+
const node1 = new TaskScheduler({
|
|
15
|
+
url: process.env.RABBITMQ_URL || 'amqp://admin:password@localhost:5672',
|
|
16
|
+
queuePrefix: 'njs_testing_'
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
await node1.initialize();
|
|
20
|
+
nodes.push({ id: 'node1', scheduler: node1 });
|
|
21
|
+
|
|
22
|
+
// Wait for it to establish leadership
|
|
23
|
+
await sleep(5000);
|
|
24
|
+
|
|
25
|
+
// Check if it's the leader
|
|
26
|
+
const node1IsLeader = node1.isLeader();
|
|
27
|
+
console.log(`Node 1: ${node1IsLeader ? '๐ LEADER' : '๐ฅ FOLLOWER'}`);
|
|
28
|
+
|
|
29
|
+
// Start second node
|
|
30
|
+
console.log('Starting node 2...');
|
|
31
|
+
const node2 = new TaskScheduler({
|
|
32
|
+
url: process.env.RABBITMQ_URL || 'amqp://admin:password@localhost:5672',
|
|
33
|
+
queuePrefix: 'njs_testing_'
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
await node2.initialize();
|
|
37
|
+
nodes.push({ id: 'node2', scheduler: node2 });
|
|
38
|
+
|
|
39
|
+
// Wait for election to stabilize
|
|
40
|
+
await sleep(5000);
|
|
41
|
+
|
|
42
|
+
// Check leader status
|
|
43
|
+
const node1IsLeader2 = node1.isLeader();
|
|
44
|
+
const node2IsLeader = node2.isLeader();
|
|
45
|
+
|
|
46
|
+
console.log(`Node 1: ${node1IsLeader2 ? '๐ LEADER' : '๐ฅ FOLLOWER'}`);
|
|
47
|
+
console.log(`Node 2: ${node2IsLeader ? '๐ LEADER' : '๐ฅ FOLLOWER'}`);
|
|
48
|
+
|
|
49
|
+
// Verify only one leader
|
|
50
|
+
const leaderCount = (node1IsLeader2 ? 1 : 0) + (node2IsLeader ? 1 : 0);
|
|
51
|
+
|
|
52
|
+
if (leaderCount === 1) {
|
|
53
|
+
console.log('โ
Election successful - exactly one leader');
|
|
54
|
+
} else {
|
|
55
|
+
console.log(`โ Election failed - ${leaderCount} leaders found`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Test leader shutdown and failover
|
|
59
|
+
console.log('\n๐ Testing leader failover...');
|
|
60
|
+
|
|
61
|
+
let currentLeader = node1IsLeader2 ? nodes[0] : nodes[1];
|
|
62
|
+
let follower = node1IsLeader2 ? nodes[1] : nodes[0];
|
|
63
|
+
|
|
64
|
+
console.log(`Shutting down current leader: ${currentLeader.id}`);
|
|
65
|
+
await currentLeader.scheduler.shutdown();
|
|
66
|
+
|
|
67
|
+
// Remove from nodes array
|
|
68
|
+
const leaderIndex = nodes.indexOf(currentLeader);
|
|
69
|
+
nodes.splice(leaderIndex, 1);
|
|
70
|
+
|
|
71
|
+
// Wait for new election
|
|
72
|
+
await sleep(8000);
|
|
73
|
+
|
|
74
|
+
// Check if follower became leader
|
|
75
|
+
const newLeaderIsLeader = follower.scheduler.isLeader();
|
|
76
|
+
console.log(`${follower.id}: ${newLeaderIsLeader ? '๐ NEW LEADER' : '๐ฅ STILL FOLLOWER'}`);
|
|
77
|
+
|
|
78
|
+
if (newLeaderIsLeader) {
|
|
79
|
+
console.log('โ
Failover successful');
|
|
80
|
+
console.log('โ
All multinode tests PASSED!');
|
|
81
|
+
} else {
|
|
82
|
+
console.log('โ Failover failed');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error('โ Test failed:', error.message);
|
|
87
|
+
} finally {
|
|
88
|
+
// Cleanup
|
|
89
|
+
console.log('\n๐งน Cleaning up...');
|
|
90
|
+
for (const node of nodes) {
|
|
91
|
+
try {
|
|
92
|
+
await node.scheduler.shutdown();
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.warn(`Warning: cleanup error for ${node.id}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
console.log('โ
Test completed');
|
|
98
|
+
|
|
99
|
+
// Force exit to avoid hanging on reconnection attempts
|
|
100
|
+
setTimeout(() => {
|
|
101
|
+
console.log('๐ช Exiting test...');
|
|
102
|
+
process.exit(0);
|
|
103
|
+
}, 2000);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function sleep(ms: number): Promise<void> {
|
|
108
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Handle uncaught errors gracefully
|
|
112
|
+
process.on('uncaughtException', (error) => {
|
|
113
|
+
console.error('Uncaught Exception (non-fatal):', error.message);
|
|
114
|
+
// Don't exit, let test continue
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
118
|
+
console.error('Unhandled Rejection (non-fatal):', reason);
|
|
119
|
+
// Don't exit, let test continue
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
testBasicElection().catch(error => {
|
|
123
|
+
console.error('โ Test execution failed:', error.message);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
// Simple multi-node test that can be run manually in separate terminals
|
|
4
|
+
import { TaskScheduler } from './src';
|
|
5
|
+
|
|
6
|
+
const nodeId = process.argv[2] || `node-${Math.floor(Math.random() * 1000)}`;
|
|
7
|
+
const isScheduler = process.argv[3] === 'scheduler';
|
|
8
|
+
|
|
9
|
+
console.log(`๐ Starting ${nodeId} ${isScheduler ? '(with job scheduling)' : '(worker only)'}`);
|
|
10
|
+
|
|
11
|
+
async function runNode() {
|
|
12
|
+
const scheduler = new TaskScheduler({
|
|
13
|
+
url: process.env.RABBITMQ_URL || 'amqp://admin:password@localhost:5672',
|
|
14
|
+
queuePrefix: 'njs_testing_'
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
await scheduler.initialize();
|
|
19
|
+
console.log(`โ
${nodeId} initialized`);
|
|
20
|
+
|
|
21
|
+
// Create worker
|
|
22
|
+
await scheduler.createWorker({
|
|
23
|
+
name: `${nodeId}-worker`,
|
|
24
|
+
concurrency: 2,
|
|
25
|
+
queues: ['test-jobs'],
|
|
26
|
+
handlers: {
|
|
27
|
+
'test-job': async (data: any) => {
|
|
28
|
+
console.log(`๐ ${nodeId} processing:`, data.message);
|
|
29
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
30
|
+
return {
|
|
31
|
+
success: true,
|
|
32
|
+
processedBy: nodeId,
|
|
33
|
+
timestamp: new Date().toISOString()
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Show node status every 10 seconds
|
|
40
|
+
setInterval(async () => {
|
|
41
|
+
try {
|
|
42
|
+
const nodeInfo = await scheduler.getNodeInfo();
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
const status = nodeInfo.isLeader ? '๐ LEADER' : '๐ฅ FOLLOWER';
|
|
45
|
+
console.log(`${nodeId}: ${status} (ID: ${nodeInfo.nodeId.substring(0, 8)}...)`);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.log(`${nodeId}: โ Status check failed`);
|
|
48
|
+
}
|
|
49
|
+
}, 10000);
|
|
50
|
+
|
|
51
|
+
// If this is the scheduler node, schedule some jobs
|
|
52
|
+
if (isScheduler) {
|
|
53
|
+
console.log(`๐ ${nodeId} will schedule jobs every 15 seconds`);
|
|
54
|
+
|
|
55
|
+
let jobCounter = 1;
|
|
56
|
+
setInterval(async () => {
|
|
57
|
+
try {
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
await scheduler.scheduleJob({
|
|
60
|
+
id: `job-${jobCounter}`,
|
|
61
|
+
name: `Test Job ${jobCounter}`,
|
|
62
|
+
handler: 'test-job',
|
|
63
|
+
data: {
|
|
64
|
+
message: `Hello from job ${jobCounter}`,
|
|
65
|
+
scheduledBy: nodeId,
|
|
66
|
+
timestamp: new Date().toISOString()
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
console.log(`๐ค ${nodeId} scheduled job-${jobCounter}`);
|
|
70
|
+
jobCounter++;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error(`โ ${nodeId} failed to schedule job:`, error.message);
|
|
73
|
+
}
|
|
74
|
+
}, 15000);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(`๐ข ${nodeId} is running and ready`);
|
|
78
|
+
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error(`โ ${nodeId} failed to start:`, error);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Graceful shutdown
|
|
86
|
+
process.on('SIGINT', async () => {
|
|
87
|
+
console.log(`\n๐ ${nodeId} shutting down...`);
|
|
88
|
+
process.exit(0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
runNode().catch(error => {
|
|
92
|
+
console.error(`โ ${nodeId} crashed:`, error);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
});
|