queen-mq 0.1.0 → 0.1.2
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/API.md +862 -752
- package/AUTH.md +2044 -0
- package/LICENSE.md +202 -0
- package/README.md +1705 -1051
- package/WEBAPP.md +1889 -0
- package/assets/dashboard-01.png +0 -0
- package/assets/queen-logo-blue.svg +210 -0
- package/assets/queen-logo-cyan.svg +210 -0
- package/assets/queen-logo-indigo.svg +210 -0
- package/assets/queen-logo-orange.svg +210 -0
- package/assets/queen-logo-pink.svg +210 -0
- package/assets/queen-logo-purple.svg +210 -0
- package/assets/queen-logo-rose.svg +239 -0
- package/assets/queen-logo.svg +263 -0
- package/examples/batch-processing.js +58 -0
- package/examples/test-complete-client.js +260 -0
- package/examples/test-dashboard-api.js +200 -0
- package/examples/test-traceid.js +147 -0
- package/package.json +17 -4
- package/server.log +1 -0
- package/src/benchmark/consumer.js +207 -0
- package/src/benchmark/consumer_multi.js +216 -0
- package/src/benchmark/producer.js +75 -0
- package/src/benchmark/producer_multi.js +115 -0
- package/src/client/client.js +300 -31
- package/src/client/queenClient.js +5 -0
- package/src/cluster-server.js +242 -0
- package/src/config.js +19 -5
- package/src/database/connection.js +42 -16
- package/src/database/poolManager.js +7 -0
- package/src/database/schema-v2.sql +194 -130
- package/src/managers/queueManagerOptimized.js +823 -933
- package/src/managers/systemEventManager.js +8 -3
- package/src/routes/messages.js +127 -57
- package/src/routes/pop.js +27 -43
- package/src/routes/resources.js +61 -27
- package/src/routes/status.js +1037 -0
- package/src/server.js +308 -272
- package/src/services/evictionService.js +57 -28
- package/src/services/retentionService.js +44 -11
- package/src/test/MIGRATION_ISSUES.md +174 -0
- package/src/test/README.md +203 -0
- package/src/test/advanced-pattern-tests.js +1137 -0
- package/src/test/bus-mode-tests.js +361 -0
- package/src/test/core-tests.js +342 -0
- package/src/test/edge-case-tests.js +561 -0
- package/src/test/enterprise-tests.js +637 -0
- package/src/test/partition-locking-tests.js +545 -0
- package/src/test/test-new.js +278 -0
- package/src/test/test.js +6 -3
- package/src/test/utils.js +169 -0
- package/src/utils/streaming.js +231 -0
- package/src/utils/uuid.js +2 -2
- package/src/websocket/wsServer.js +10 -3
- package/test-keepalive-v2.sh +22 -0
- package/webapp/COLOR_GUIDE.md +118 -0
- package/webapp/README.md +143 -0
- package/webapp/index.html +14 -0
- package/webapp/package-lock.json +3184 -0
- package/webapp/package.json +25 -0
- package/webapp/postcss.config.js +7 -0
- package/webapp/public/assets/queen-logo-blue.svg +210 -0
- package/webapp/public/assets/queen-logo-cyan.svg +210 -0
- package/webapp/public/assets/queen-logo-indigo.svg +210 -0
- package/webapp/public/assets/queen-logo-orange.svg +210 -0
- package/webapp/public/assets/queen-logo-pink.svg +210 -0
- package/webapp/public/assets/queen-logo-purple.svg +210 -0
- package/webapp/public/assets/queen-logo-rose.svg +239 -0
- package/webapp/public/assets/queen-logo.svg +263 -0
- package/webapp/src/App.vue +19 -0
- package/webapp/src/api/analytics.js +10 -0
- package/webapp/src/api/client.js +29 -0
- package/webapp/src/api/consumers.js +52 -0
- package/webapp/src/api/health.js +7 -0
- package/webapp/src/api/messages.js +26 -0
- package/webapp/src/api/queues.js +14 -0
- package/webapp/src/api/resources.js +8 -0
- package/webapp/src/assets/styles/main.css +357 -0
- package/webapp/src/components/analytics/AnalyticsFilters.vue +87 -0
- package/webapp/src/components/analytics/AnalyticsMetrics.vue +57 -0
- package/webapp/src/components/analytics/MessageDistributionChart.vue +111 -0
- package/webapp/src/components/analytics/MessageFlowChart.vue +173 -0
- package/webapp/src/components/analytics/TimeRangeSelector.vue +27 -0
- package/webapp/src/components/analytics/TopQueuesChart.vue +132 -0
- package/webapp/src/components/common/ConfirmDialog.vue +56 -0
- package/webapp/src/components/common/LoadingSpinner.vue +6 -0
- package/webapp/src/components/common/MetricCard.vue +43 -0
- package/webapp/src/components/common/StatusBadge.vue +45 -0
- package/webapp/src/components/dashboard/MessageStatusCard.vue +50 -0
- package/webapp/src/components/dashboard/PerformanceCard.vue +38 -0
- package/webapp/src/components/dashboard/ThroughputChart.vue +182 -0
- package/webapp/src/components/dashboard/TopQueuesTable.vue +53 -0
- package/webapp/src/components/layout/AppLayout.vue +110 -0
- package/webapp/src/components/layout/AppSidebar.vue +304 -0
- package/webapp/src/components/messages/MessageDetailPanel.vue +242 -0
- package/webapp/src/components/messages/MessageFilters.vue +114 -0
- package/webapp/src/components/queue-detail/PartitionList.vue +79 -0
- package/webapp/src/components/queue-detail/PushMessageModal.vue +175 -0
- package/webapp/src/components/queue-detail/QueueConfig.vue +63 -0
- package/webapp/src/components/queue-detail/QueueDetailHeader.vue +53 -0
- package/webapp/src/components/queue-detail/RecentMessages.vue +76 -0
- package/webapp/src/components/queues/CreateQueueModal.vue +193 -0
- package/webapp/src/components/queues/QueueFilters.vue +90 -0
- package/webapp/src/composables/useApi.js +34 -0
- package/webapp/src/composables/useTheme.js +36 -0
- package/webapp/src/main.js +11 -0
- package/webapp/src/router/index.js +42 -0
- package/webapp/src/utils/colors.js +96 -0
- package/webapp/src/utils/formatters.js +49 -0
- package/webapp/src/views/Analytics.vue +377 -0
- package/webapp/src/views/ConsumerGroups.vue +433 -0
- package/webapp/src/views/Dashboard.vue +418 -0
- package/webapp/src/views/Messages.vue +361 -0
- package/webapp/src/views/QueueDetail.vue +582 -0
- package/webapp/src/views/Queues.vue +496 -0
- package/webapp/tailwind.config.js +25 -0
- package/webapp/vite.config.js +10 -0
- package/CACHE.md +0 -519
- package/DASHBOARD-V3.md +0 -478
- package/DASHBOARD.md +0 -382
- package/MOD_QUEUE.md +0 -453
- package/PARTITION_LOCKING_DESIGN.md +0 -989
- package/PLAN.md +0 -707
- package/QUERY_ANALSYS.md +0 -72
- package/QUEUE_BUS.md +0 -334
- package/V2-PLAN.md +0 -236
- package/dashboard/.vscode/extensions.json +0 -3
- package/dashboard/README.md +0 -5
- package/dashboard/index.html +0 -14
- package/dashboard/package-lock.json +0 -1458
- package/dashboard/package.json +0 -25
- package/dashboard/public/vite.svg +0 -1
- package/dashboard/src/App.vue +0 -29
- package/dashboard/src/assets/styles/main.css +0 -908
- package/dashboard/src/assets/vue.svg +0 -1
- package/dashboard/src/components/cards/MetricCard.vue +0 -298
- package/dashboard/src/components/charts/QueueDepthChart.vue +0 -276
- package/dashboard/src/components/charts/QueueLagChart.vue +0 -436
- package/dashboard/src/components/charts/ThroughputChart.vue +0 -302
- package/dashboard/src/components/common/ActivityFeed.vue +0 -251
- package/dashboard/src/components/layout/AppHeader.vue +0 -208
- package/dashboard/src/components/layout/AppLayout.vue +0 -88
- package/dashboard/src/components/layout/AppSidebar.vue +0 -261
- package/dashboard/src/main.js +0 -44
- package/dashboard/src/router.js +0 -54
- package/dashboard/src/services/api.js +0 -187
- package/dashboard/src/services/websocket.js +0 -167
- package/dashboard/src/utils/constants.js +0 -56
- package/dashboard/src/utils/helpers.js +0 -118
- package/dashboard/src/views/Analytics.vue +0 -912
- package/dashboard/src/views/Dashboard.vue +0 -906
- package/dashboard/src/views/Messages.vue +0 -437
- package/dashboard/src/views/QueueDetail.vue +0 -501
- package/dashboard/src/views/Queues.vue +0 -333
- package/dashboard/vite.config.js +0 -30
- package/debug-namespace.js +0 -110
- package/docs/long-polling.md +0 -159
- package/docs/multi-server-cache-solutions.md +0 -185
- package/docs/performance-tuning.md +0 -222
- package/src/routes/analytics.js +0 -812
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
# Multi-Server Cache Consistency Solutions
|
|
2
|
-
|
|
3
|
-
## Problem
|
|
4
|
-
When running multiple Queen servers, each server maintains its own in-memory resource cache with a 1-minute TTL. Configuration changes on one server are not reflected on other servers until the cache expires.
|
|
5
|
-
|
|
6
|
-
## Solutions
|
|
7
|
-
|
|
8
|
-
### 1. **Disable Cache in Multi-Server Mode** (Quick Fix)
|
|
9
|
-
Set cache TTL to 0 or very short duration when running multiple servers.
|
|
10
|
-
|
|
11
|
-
```javascript
|
|
12
|
-
// In src/managers/resourceCache.js
|
|
13
|
-
const TTL = process.env.QUEEN_CACHE_TTL ? parseInt(process.env.QUEEN_CACHE_TTL) : 60000;
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Run servers with:
|
|
17
|
-
```bash
|
|
18
|
-
QUEEN_CACHE_TTL=0 PORT=6632 node src/server.js
|
|
19
|
-
QUEEN_CACHE_TTL=0 PORT=6633 node src/server.js
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### 2. **Cache Invalidation via Database Triggers** (Recommended)
|
|
23
|
-
Add a `cache_invalidation` table and use database triggers to notify servers of changes.
|
|
24
|
-
|
|
25
|
-
```sql
|
|
26
|
-
-- Add to schema
|
|
27
|
-
CREATE TABLE queen.cache_invalidations (
|
|
28
|
-
id SERIAL PRIMARY KEY,
|
|
29
|
-
resource_type VARCHAR(50) NOT NULL,
|
|
30
|
-
resource_key VARCHAR(255) NOT NULL,
|
|
31
|
-
invalidated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
CREATE INDEX idx_cache_invalidations_time ON queen.cache_invalidations(invalidated_at);
|
|
35
|
-
|
|
36
|
-
-- Trigger on queue updates
|
|
37
|
-
CREATE OR REPLACE FUNCTION queen.notify_cache_invalidation()
|
|
38
|
-
RETURNS TRIGGER AS $$
|
|
39
|
-
BEGIN
|
|
40
|
-
INSERT INTO queen.cache_invalidations (resource_type, resource_key)
|
|
41
|
-
VALUES ('queue', NEW.name);
|
|
42
|
-
|
|
43
|
-
PERFORM pg_notify('cache_invalidation', json_build_object(
|
|
44
|
-
'type', 'queue',
|
|
45
|
-
'key', NEW.name
|
|
46
|
-
)::text);
|
|
47
|
-
|
|
48
|
-
RETURN NEW;
|
|
49
|
-
END;
|
|
50
|
-
$$ LANGUAGE plpgsql;
|
|
51
|
-
|
|
52
|
-
CREATE TRIGGER queue_cache_invalidation
|
|
53
|
-
AFTER UPDATE ON queen.queues
|
|
54
|
-
FOR EACH ROW
|
|
55
|
-
EXECUTE FUNCTION queen.notify_cache_invalidation();
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### 3. **Redis-Based Distributed Cache** (Best for Scale)
|
|
59
|
-
Replace in-memory cache with Redis for shared caching across servers.
|
|
60
|
-
|
|
61
|
-
```javascript
|
|
62
|
-
// src/managers/redisResourceCache.js
|
|
63
|
-
import Redis from 'ioredis';
|
|
64
|
-
|
|
65
|
-
export const createRedisResourceCache = (redisConfig) => {
|
|
66
|
-
const redis = new Redis(redisConfig);
|
|
67
|
-
const TTL = 60; // seconds
|
|
68
|
-
|
|
69
|
-
const getCacheKey = (queue, partition) =>
|
|
70
|
-
`queen:resource:${queue}:${partition || 'Default'}`;
|
|
71
|
-
|
|
72
|
-
const checkResource = async (queue, partition) => {
|
|
73
|
-
const key = getCacheKey(queue, partition);
|
|
74
|
-
const cached = await redis.get(key);
|
|
75
|
-
return cached ? JSON.parse(cached) : null;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const cacheResource = async (queue, partition, data) => {
|
|
79
|
-
const key = getCacheKey(queue, partition);
|
|
80
|
-
await redis.setex(key, TTL, JSON.stringify(data));
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const invalidate = async (queue, partition) => {
|
|
84
|
-
if (queue && partition) {
|
|
85
|
-
await redis.del(getCacheKey(queue, partition));
|
|
86
|
-
} else if (queue) {
|
|
87
|
-
const keys = await redis.keys(`queen:resource:${queue}:*`);
|
|
88
|
-
if (keys.length > 0) {
|
|
89
|
-
await redis.del(...keys);
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
const keys = await redis.keys('queen:resource:*');
|
|
93
|
-
if (keys.length > 0) {
|
|
94
|
-
await redis.del(...keys);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
checkResource,
|
|
101
|
-
cacheResource,
|
|
102
|
-
invalidate,
|
|
103
|
-
invalidateQueue: (queue) => invalidate(queue)
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### 4. **Polling-Based Cache Invalidation** (Simple)
|
|
109
|
-
Each server periodically checks for configuration changes.
|
|
110
|
-
|
|
111
|
-
```javascript
|
|
112
|
-
// Add to resourceCache.js
|
|
113
|
-
const pollForChanges = async (pool) => {
|
|
114
|
-
const result = await pool.query(`
|
|
115
|
-
SELECT name, updated_at
|
|
116
|
-
FROM queen.queues
|
|
117
|
-
WHERE updated_at > $1
|
|
118
|
-
`, [lastCheckTime]);
|
|
119
|
-
|
|
120
|
-
for (const row of result.rows) {
|
|
121
|
-
invalidateQueue(row.name);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
lastCheckTime = new Date();
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
// Poll every 5 seconds
|
|
128
|
-
setInterval(() => pollForChanges(pool), 5000);
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### 5. **Event-Based Invalidation via Message Queue**
|
|
132
|
-
Use the Queen queue itself to propagate cache invalidation events.
|
|
133
|
-
|
|
134
|
-
```javascript
|
|
135
|
-
// When configuration changes on one server
|
|
136
|
-
await client.push({
|
|
137
|
-
items: [{
|
|
138
|
-
queue: '_system_cache_invalidation',
|
|
139
|
-
partition: 'Default',
|
|
140
|
-
payload: {
|
|
141
|
-
action: 'invalidate',
|
|
142
|
-
resourceType: 'queue',
|
|
143
|
-
resourceKey: queueName,
|
|
144
|
-
timestamp: Date.now()
|
|
145
|
-
}
|
|
146
|
-
}]
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// All servers consume from this queue
|
|
150
|
-
client.consume({
|
|
151
|
-
queue: '_system_cache_invalidation',
|
|
152
|
-
handler: async (message) => {
|
|
153
|
-
const { resourceType, resourceKey } = message.payload;
|
|
154
|
-
if (resourceType === 'queue') {
|
|
155
|
-
resourceCache.invalidateQueue(resourceKey);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
## Recommended Approach
|
|
162
|
-
|
|
163
|
-
For your immediate testing needs, use **Solution 1** (disable cache):
|
|
164
|
-
```bash
|
|
165
|
-
# Start servers without cache
|
|
166
|
-
QUEEN_CACHE_TTL=0 PORT=6632 node src/server.js
|
|
167
|
-
QUEEN_CACHE_TTL=0 PORT=6633 node src/server.js
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
For production multi-server deployment:
|
|
171
|
-
- **Small scale (2-3 servers)**: Solution 2 (Database triggers with LISTEN/NOTIFY)
|
|
172
|
-
- **Medium scale (4-10 servers)**: Solution 3 (Redis cache)
|
|
173
|
-
- **Large scale (10+ servers)**: Solution 3 (Redis) + Solution 5 (Event-based)
|
|
174
|
-
|
|
175
|
-
## Testing Cache Behavior
|
|
176
|
-
|
|
177
|
-
After implementing a solution, run:
|
|
178
|
-
```bash
|
|
179
|
-
node examples/test-cache-multi-server.js
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
The test should show:
|
|
183
|
-
- Both servers returning the same messages ✅
|
|
184
|
-
- Configuration changes immediately visible on both servers ✅
|
|
185
|
-
- No cache inconsistency warnings ✅
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
# Performance Tuning Guide for Queen
|
|
2
|
-
|
|
3
|
-
## Database Connection Pool Optimization
|
|
4
|
-
|
|
5
|
-
When running Queen under high load, you may encounter database connection pool exhaustion errors:
|
|
6
|
-
```
|
|
7
|
-
Error: timeout exceeded when trying to connect
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
This happens when the rate of incoming requests exceeds the available database connections.
|
|
11
|
-
|
|
12
|
-
## Solution 1: Increase Connection Pool Size
|
|
13
|
-
|
|
14
|
-
Set these environment variables before starting the server:
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
# Increase the connection pool size (default is 20)
|
|
18
|
-
export DB_POOL_SIZE=50
|
|
19
|
-
|
|
20
|
-
# Increase connection timeout (default is 2000ms)
|
|
21
|
-
export DB_CONNECTION_TIMEOUT=5000
|
|
22
|
-
|
|
23
|
-
# Start the server
|
|
24
|
-
npm start
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Solution 2: Optimize PostgreSQL Settings
|
|
28
|
-
|
|
29
|
-
Edit your `postgresql.conf`:
|
|
30
|
-
|
|
31
|
-
```conf
|
|
32
|
-
# Increase maximum connections
|
|
33
|
-
max_connections = 200
|
|
34
|
-
|
|
35
|
-
# Connection pooling
|
|
36
|
-
shared_preload_libraries = 'pg_stat_statements'
|
|
37
|
-
|
|
38
|
-
# Memory settings for better performance
|
|
39
|
-
shared_buffers = 256MB
|
|
40
|
-
effective_cache_size = 1GB
|
|
41
|
-
work_mem = 4MB
|
|
42
|
-
maintenance_work_mem = 64MB
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Solution 3: Use Batch Inserts (Database Optimization)
|
|
46
|
-
|
|
47
|
-
The current implementation processes messages individually within a transaction. For better performance under high load, consider using batch inserts.
|
|
48
|
-
|
|
49
|
-
### Current Implementation (Sequential)
|
|
50
|
-
```javascript
|
|
51
|
-
// Process each item individually
|
|
52
|
-
for (const item of items) {
|
|
53
|
-
// Individual INSERT for each message
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Optimized Implementation (Batch)
|
|
58
|
-
```sql
|
|
59
|
-
-- Use single INSERT with multiple VALUES
|
|
60
|
-
INSERT INTO queen.messages (transaction_id, queue_id, payload, status)
|
|
61
|
-
VALUES
|
|
62
|
-
($1, $2, $3, 'pending'),
|
|
63
|
-
($4, $5, $6, 'pending'),
|
|
64
|
-
...
|
|
65
|
-
RETURNING id, transaction_id;
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Solution 4: Implement Connection Pooling with PgBouncer
|
|
69
|
-
|
|
70
|
-
For production environments with very high load, use PgBouncer as a connection pooler:
|
|
71
|
-
|
|
72
|
-
1. Install PgBouncer:
|
|
73
|
-
```bash
|
|
74
|
-
# macOS
|
|
75
|
-
brew install pgbouncer
|
|
76
|
-
|
|
77
|
-
# Linux
|
|
78
|
-
apt-get install pgbouncer
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
2. Configure PgBouncer (`/etc/pgbouncer/pgbouncer.ini`):
|
|
82
|
-
```ini
|
|
83
|
-
[databases]
|
|
84
|
-
queen = host=localhost port=5432 dbname=postgres
|
|
85
|
-
|
|
86
|
-
[pgbouncer]
|
|
87
|
-
listen_port = 6432
|
|
88
|
-
listen_addr = *
|
|
89
|
-
auth_type = md5
|
|
90
|
-
auth_file = /etc/pgbouncer/userlist.txt
|
|
91
|
-
pool_mode = transaction
|
|
92
|
-
max_client_conn = 1000
|
|
93
|
-
default_pool_size = 50
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
3. Update Queen to connect through PgBouncer:
|
|
97
|
-
```bash
|
|
98
|
-
export PG_PORT=6432 # PgBouncer port
|
|
99
|
-
npm start
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Recommended Production Settings
|
|
103
|
-
|
|
104
|
-
For a production environment handling high message throughput:
|
|
105
|
-
|
|
106
|
-
### Environment Variables
|
|
107
|
-
```bash
|
|
108
|
-
# Database
|
|
109
|
-
DB_POOL_SIZE=50
|
|
110
|
-
DB_CONNECTION_TIMEOUT=5000
|
|
111
|
-
DB_IDLE_TIMEOUT=30000
|
|
112
|
-
|
|
113
|
-
# Application
|
|
114
|
-
NODE_ENV=production
|
|
115
|
-
NODE_OPTIONS="--max-old-space-size=4096"
|
|
116
|
-
|
|
117
|
-
# Monitoring
|
|
118
|
-
LOG_LEVEL=warn
|
|
119
|
-
ENABLE_METRICS=true
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### Example High-Load Configuration
|
|
123
|
-
|
|
124
|
-
For sustained load of 1000+ messages/second:
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
# Start server with optimized settings
|
|
128
|
-
DB_POOL_SIZE=100 \
|
|
129
|
-
DB_CONNECTION_TIMEOUT=10000 \
|
|
130
|
-
NODE_OPTIONS="--max-old-space-size=8192" \
|
|
131
|
-
npm start
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Testing Under Load
|
|
135
|
-
|
|
136
|
-
### Reasonable Load Test
|
|
137
|
-
```bash
|
|
138
|
-
# 10 messages per batch, every 100ms = ~100 msg/sec
|
|
139
|
-
BATCH_SIZE=10 INTERVAL=100 node examples/continuous-producer.js
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### Medium Load Test
|
|
143
|
-
```bash
|
|
144
|
-
# 50 messages per batch, every 500ms = ~100 msg/sec
|
|
145
|
-
BATCH_SIZE=50 INTERVAL=500 node examples/continuous-producer.js
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### High Load Test (requires tuning)
|
|
149
|
-
```bash
|
|
150
|
-
# First, increase DB pool
|
|
151
|
-
export DB_POOL_SIZE=100
|
|
152
|
-
|
|
153
|
-
# Then run high load producer
|
|
154
|
-
# 100 messages per batch, every 1000ms = ~100 msg/sec
|
|
155
|
-
BATCH_SIZE=100 INTERVAL=1000 node examples/continuous-producer.js
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
## Monitoring Performance
|
|
159
|
-
|
|
160
|
-
Monitor these metrics to identify bottlenecks:
|
|
161
|
-
|
|
162
|
-
1. **Database Connections**
|
|
163
|
-
```sql
|
|
164
|
-
-- Check active connections
|
|
165
|
-
SELECT count(*) FROM pg_stat_activity;
|
|
166
|
-
|
|
167
|
-
-- Check connections by state
|
|
168
|
-
SELECT state, count(*)
|
|
169
|
-
FROM pg_stat_activity
|
|
170
|
-
GROUP BY state;
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
2. **Connection Pool Status**
|
|
174
|
-
```javascript
|
|
175
|
-
// Add monitoring endpoint to server
|
|
176
|
-
app.get('/metrics/pool', (req, res) => {
|
|
177
|
-
res.json({
|
|
178
|
-
totalCount: pool.totalCount,
|
|
179
|
-
idleCount: pool.idleCount,
|
|
180
|
-
waitingCount: pool.waitingCount
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
3. **Message Throughput**
|
|
186
|
-
```bash
|
|
187
|
-
# Monitor message insertion rate
|
|
188
|
-
watch -n 1 "psql -c 'SELECT count(*) FROM queen.messages WHERE created_at > NOW() - INTERVAL '\''1 minute'\'';'"
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## Best Practices
|
|
192
|
-
|
|
193
|
-
1. **Start Conservative**: Begin with lower message rates and gradually increase
|
|
194
|
-
2. **Monitor Resources**: Watch CPU, memory, and database connections
|
|
195
|
-
3. **Use Batching**: Process messages in reasonable batches (10-100 per batch)
|
|
196
|
-
4. **Implement Backpressure**: Slow down producers when consumers can't keep up
|
|
197
|
-
5. **Scale Horizontally**: Run multiple Queen instances behind a load balancer
|
|
198
|
-
6. **Use Read Replicas**: For analytics and read-heavy operations
|
|
199
|
-
|
|
200
|
-
## Troubleshooting
|
|
201
|
-
|
|
202
|
-
### "timeout exceeded when trying to connect"
|
|
203
|
-
- Increase `DB_POOL_SIZE`
|
|
204
|
-
- Increase `DB_CONNECTION_TIMEOUT`
|
|
205
|
-
- Check PostgreSQL `max_connections`
|
|
206
|
-
- Consider using PgBouncer
|
|
207
|
-
|
|
208
|
-
### "Push request aborted"
|
|
209
|
-
- Client timeout is too short
|
|
210
|
-
- Increase client timeout in producer
|
|
211
|
-
- Reduce batch size
|
|
212
|
-
|
|
213
|
-
### High Memory Usage
|
|
214
|
-
- Reduce batch sizes
|
|
215
|
-
- Increase Node.js heap size with `--max-old-space-size`
|
|
216
|
-
- Implement message pagination
|
|
217
|
-
|
|
218
|
-
### Slow Message Processing
|
|
219
|
-
- Add database indexes
|
|
220
|
-
- Use batch operations
|
|
221
|
-
- Implement caching for frequently accessed data
|
|
222
|
-
- Consider partitioning large tables
|