nodejs-task-scheduler 1.0.9 โ 1.0.11
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 +107 -26
- 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/nul +1 -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;YAkDjB,YAAY;YAoBZ,cAAc;YAuBd,aAAa;YA2Cb,sBAAsB;IAmFpC,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,8 +104,18 @@ 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 {
|
|
112
|
+
// Add a small random delay to reduce collision probability
|
|
113
|
+
const delayMs = Math.floor(Math.random() * 1000); // 0-1000ms
|
|
114
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
115
|
+
// Check if we're still running after the delay
|
|
116
|
+
if (!this.isRunning) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
104
119
|
// Try to consume from election queue exclusively
|
|
105
120
|
const consumerResult = await channel.consume(this.electionQueue, () => { }, // We don't process messages, just need exclusive access
|
|
106
121
|
{
|
|
@@ -108,15 +123,23 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
108
123
|
noAck: true
|
|
109
124
|
});
|
|
110
125
|
if (consumerResult) {
|
|
126
|
+
this.consumerTag = consumerResult.consumerTag;
|
|
111
127
|
await this.becomeLeader();
|
|
112
128
|
}
|
|
113
129
|
}
|
|
114
130
|
catch (error) {
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
// Handle ACCESS_REFUSED (403) or exclusive access errors
|
|
132
|
+
if (error.code === 403 ||
|
|
133
|
+
(error.message && (error.message.includes('ACCESS_REFUSED') ||
|
|
134
|
+
error.message.includes('exclusive') ||
|
|
135
|
+
error.message.includes('in exclusive use')))) {
|
|
136
|
+
// Another node is already the leader - this is expected behavior
|
|
137
|
+
console.log(`Node ${this.nodeId} found existing leader, becoming follower`);
|
|
117
138
|
await this.becomeFollower();
|
|
118
139
|
}
|
|
119
140
|
else {
|
|
141
|
+
// Unexpected error, re-throw
|
|
142
|
+
console.error(`Unexpected error during leadership attempt for node ${this.nodeId}:`, error);
|
|
120
143
|
throw error;
|
|
121
144
|
}
|
|
122
145
|
}
|
|
@@ -162,6 +185,9 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
162
185
|
return;
|
|
163
186
|
}
|
|
164
187
|
try {
|
|
188
|
+
if (!this.connection.isConnected()) {
|
|
189
|
+
throw new Error('Not connected to RabbitMQ');
|
|
190
|
+
}
|
|
165
191
|
const channel = this.connection.getChannel();
|
|
166
192
|
const heartbeatMessage = {
|
|
167
193
|
nodeId: this.nodeId,
|
|
@@ -191,34 +217,66 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
191
217
|
return;
|
|
192
218
|
}
|
|
193
219
|
try {
|
|
220
|
+
if (!this.connection.isConnected()) {
|
|
221
|
+
throw new Error('Not connected to RabbitMQ');
|
|
222
|
+
}
|
|
194
223
|
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();
|
|
224
|
+
try {
|
|
225
|
+
await channel.consume(this.heartbeatQueue, async (msg) => {
|
|
226
|
+
if (!msg || !this.isRunning) {
|
|
227
|
+
return;
|
|
205
228
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
229
|
+
try {
|
|
230
|
+
const heartbeat = JSON.parse(msg.content.toString());
|
|
231
|
+
if (heartbeat.nodeId !== this.nodeId) {
|
|
232
|
+
// Received heartbeat from current leader
|
|
233
|
+
this.lastHeartbeat = new Date(heartbeat.timestamp);
|
|
234
|
+
this.resetLeadershipTimeout();
|
|
235
|
+
}
|
|
236
|
+
channel.ack(msg);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
console.error('Error processing heartbeat:', error);
|
|
240
|
+
try {
|
|
241
|
+
channel.nack(msg, false, false);
|
|
242
|
+
}
|
|
243
|
+
catch (nackError) {
|
|
244
|
+
// Ignore nack errors during cleanup
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}, { noAck: false });
|
|
248
|
+
}
|
|
249
|
+
catch (consumeError) {
|
|
250
|
+
throw new Error(`Failed to consume heartbeat queue: ${consumeError.message}`);
|
|
251
|
+
}
|
|
213
252
|
// Start timeout to detect leader failure
|
|
214
253
|
this.resetLeadershipTimeout();
|
|
215
254
|
}
|
|
216
255
|
catch (error) {
|
|
217
|
-
|
|
256
|
+
// Suppress expected errors during election and cleanup
|
|
257
|
+
const isExpectedError = error.message && (error.message.includes('NOT_FOUND') ||
|
|
258
|
+
error.message.includes('Not connected to RabbitMQ') ||
|
|
259
|
+
error.message.includes('not connected') ||
|
|
260
|
+
error.message.includes('ACCESS_REFUSED') ||
|
|
261
|
+
error.message.includes('in exclusive use')) || error.code === 404 || error.code === 403;
|
|
262
|
+
if (!isExpectedError) {
|
|
263
|
+
console.error(`Failed to monitor heartbeat for node ${this.nodeId}:`, error.message);
|
|
264
|
+
}
|
|
218
265
|
// If we can't monitor heartbeat, try to start election after a delay
|
|
219
266
|
setTimeout(async () => {
|
|
220
267
|
if (this.isRunning && this.state === LeadershipState.FOLLOWER) {
|
|
221
|
-
|
|
268
|
+
try {
|
|
269
|
+
await this.startElection();
|
|
270
|
+
}
|
|
271
|
+
catch (retryError) {
|
|
272
|
+
const isRetryExpectedError = retryError.message && (retryError.message.includes('NOT_FOUND') ||
|
|
273
|
+
retryError.message.includes('not connected') ||
|
|
274
|
+
retryError.message.includes('ACCESS_REFUSED') ||
|
|
275
|
+
retryError.message.includes('in exclusive use')) || retryError.code === 404 || retryError.code === 403;
|
|
276
|
+
if (!isRetryExpectedError) {
|
|
277
|
+
console.error(`Retry election failed for node ${this.nodeId}:`, retryError.message);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
222
280
|
}
|
|
223
281
|
}, this.heartbeatInterval);
|
|
224
282
|
}
|
|
@@ -245,11 +303,14 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
245
303
|
}
|
|
246
304
|
// Cancel exclusive consumption to allow other nodes to become leader
|
|
247
305
|
try {
|
|
248
|
-
|
|
249
|
-
|
|
306
|
+
if (this.consumerTag && this.connection.isConnected()) {
|
|
307
|
+
const channel = this.connection.getChannel();
|
|
308
|
+
await channel.cancel(this.consumerTag);
|
|
309
|
+
this.consumerTag = undefined;
|
|
310
|
+
}
|
|
250
311
|
}
|
|
251
312
|
catch (error) {
|
|
252
|
-
console.warn('Error canceling election queue consumption:', error);
|
|
313
|
+
console.warn('Error canceling election queue consumption:', error.message);
|
|
253
314
|
}
|
|
254
315
|
await this.becomeFollower();
|
|
255
316
|
}
|
|
@@ -258,6 +319,9 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
258
319
|
this.cleanupTimer = setInterval(async () => {
|
|
259
320
|
if (this.isRunning && this.state === LeadershipState.FOLLOWER) {
|
|
260
321
|
try {
|
|
322
|
+
if (!this.connection.isConnected()) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
261
325
|
const channel = this.connection.getChannel();
|
|
262
326
|
// Only purge if queue has too many messages (check queue info)
|
|
263
327
|
const queueInfo = await channel.checkQueue(this.heartbeatQueue);
|
|
@@ -267,13 +331,18 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
267
331
|
}
|
|
268
332
|
}
|
|
269
333
|
catch (error) {
|
|
270
|
-
// Queue might not exist yet, ignore error
|
|
334
|
+
// Queue might not exist yet or connection issues, ignore error
|
|
335
|
+
console.debug(`Cleanup error (ignored): ${error.message}`);
|
|
271
336
|
}
|
|
272
337
|
}
|
|
273
338
|
}, 60000); // Every minute
|
|
274
339
|
}
|
|
275
340
|
async cleanupHeartbeatQueue() {
|
|
276
341
|
try {
|
|
342
|
+
if (!this.connection.isConnected()) {
|
|
343
|
+
// Silently skip cleanup when not connected - this is expected during shutdown
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
277
346
|
const channel = this.connection.getChannel();
|
|
278
347
|
// Purge any remaining messages from heartbeat queue
|
|
279
348
|
await channel.purgeQueue(this.heartbeatQueue);
|
|
@@ -281,7 +350,19 @@ class MasterElection extends events_1.EventEmitter {
|
|
|
281
350
|
await channel.deleteQueue(this.heartbeatQueue, { ifEmpty: true });
|
|
282
351
|
}
|
|
283
352
|
catch (error) {
|
|
284
|
-
console.warn(`Error cleaning up heartbeat queue for node ${this.nodeId}:`, error);
|
|
353
|
+
console.warn(`Error cleaning up heartbeat queue for node ${this.nodeId}:`, error.message);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
async waitForConnection() {
|
|
357
|
+
const maxWaitTime = 30000; // 30 seconds
|
|
358
|
+
const checkInterval = 100; // 100ms
|
|
359
|
+
let waitTime = 0;
|
|
360
|
+
while (!this.connection.isConnected() && waitTime < maxWaitTime) {
|
|
361
|
+
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
362
|
+
waitTime += checkInterval;
|
|
363
|
+
}
|
|
364
|
+
if (!this.connection.isConnected()) {
|
|
365
|
+
throw new Error('Failed to establish RabbitMQ connection within timeout period');
|
|
285
366
|
}
|
|
286
367
|
}
|
|
287
368
|
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/nul
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
error during connect: Post "http://%2F%2F.%2Fpipe%2FdockerDesktopLinuxEngine/v1.51/containers/rabbitmq-test/stop": open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.
|
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
|
+
});
|