Skip to content

Commit f5ed7fb

Browse files
committed
test(chaos): add WS portfolioFeed concurrent load test with CI integration
Add a chaos/load test script under scripts/chaos/ simulating a large number of concurrent WebSocket subscriptions to portfolioFeed.ts. Measures connection acceptance latency, message delivery latency, and server resource usage under load. Identifies and documents the practical concurrent-connection ceiling for capacity planning. - New script: scripts/chaos/ws-portfolio-feed-load-test.mjs - Configurable connections, batch size, duration, ramp strategy - Automatic ceiling assessment based on failure/drop/latency thresholds - Reports P50/P75/P95/P99 percentiles for all latency metrics - Polls backend /metrics endpoint for server resource usage during test - Writes JSON results file when CHAOS_WS_RESULTS_DIR is set - Added npm script: test:chaos:ws-load - CI: weekly scheduled job in performance-test.yml workflow Closes #1530
1 parent b5dca8e commit f5ed7fb

3 files changed

Lines changed: 948 additions & 0 deletions

File tree

.github/workflows/performance-test.yml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,124 @@ on:
77
- develop
88
paths:
99
- 'backend/**'
10+
- 'scripts/chaos/**'
1011
- '.github/workflows/performance-test.yml'
1112
pull_request:
1213
branches:
1314
- main
1415
- develop
1516
paths:
1617
- 'backend/**'
18+
- 'scripts/chaos/**'
1719
- '.github/workflows/performance-test.yml'
1820
workflow_dispatch:
21+
schedule:
22+
# Weekly capacity verification: every Monday at 08:00 UTC
23+
- cron: '0 8 * * 1'
1924

2025
permissions:
2126
contents: read
2227
checks: write
2328
actions: write
2429

2530
jobs:
31+
ws-portfolio-feed-load-test:
32+
runs-on: ubuntu-latest
33+
timeout-minutes: 15
34+
35+
steps:
36+
- name: Checkout code
37+
uses: actions/checkout@v4
38+
39+
- name: Setup Node.js
40+
uses: actions/setup-node@v4
41+
with:
42+
node-version: '20.19.0'
43+
cache: 'npm'
44+
cache-dependency-path: 'backend/package-lock.json'
45+
46+
- name: Install backend dependencies
47+
working-directory: ./backend
48+
run: npm ci
49+
50+
- name: Build backend
51+
working-directory: ./backend
52+
run: npm run build
53+
54+
- name: Run WS portfolio feed load test
55+
timeout-minutes: 8
56+
run: |
57+
# Set minimal environment for backend startup
58+
export NODE_ENV=test
59+
export PORT=3001
60+
export DATABASE_URL="sqlite::memory:"
61+
export JWT_SECRET="test-secret-key-for-ws-load-testing"
62+
export STELLAR_NETWORK_PASSPHRASE="Test SDF Network ; September 2015"
63+
export CORS_ORIGINS="http://localhost:3000,http://localhost:5173"
64+
export LOG_LEVEL="warn"
65+
export AUTH_ENABLED="false"
66+
export ENABLE_STARTUP_SELF_TEST="false"
67+
# Resolve ws package from backend's node_modules
68+
export NODE_PATH="backend/node_modules"
69+
70+
# Start backend in background (use working-directory approach for reliable PID capture)
71+
node backend/dist/index.js &
72+
BACKEND_PID=$!
73+
74+
# Wait for backend to become ready
75+
echo "Waiting for backend to become ready..."
76+
for i in $(seq 1 30); do
77+
if curl -s http://localhost:3001/health > /dev/null 2>&1; then
78+
echo "Backend is ready after ${i}s"
79+
break
80+
fi
81+
sleep 1
82+
done
83+
84+
# Create results directory
85+
mkdir -p ws-load-test-results
86+
87+
# Run the WS portfolio feed load test
88+
echo "Starting WS portfolio feed load test..."
89+
CHAOS_WS_BACKEND_URL="http://localhost:3001" \
90+
CHAOS_WS_CONCURRENT_CONNECTIONS="50" \
91+
CHAOS_WS_BATCH_SIZE="10" \
92+
CHAOS_WS_BATCH_DELAY_MS="200" \
93+
CHAOS_WS_DURATION_MS="30000" \
94+
CHAOS_WS_AUTH_ENABLED="false" \
95+
CHAOS_WS_RESULTS_DIR="ws-load-test-results" \
96+
node scripts/chaos/ws-portfolio-feed-load-test.mjs
97+
LOAD_TEST_EXIT=$?
98+
99+
# Cleanup
100+
kill $BACKEND_PID 2>/dev/null || true
101+
wait $BACKEND_PID 2>/dev/null || true
102+
103+
exit $LOAD_TEST_EXIT
104+
env:
105+
NODE_OPTIONS: '--max-old-space-size=2048'
106+
107+
- name: Upload load test report
108+
if: always()
109+
uses: actions/upload-artifact@v4
110+
with:
111+
name: ws-load-test-report
112+
path: |
113+
ws-load-test-results/
114+
retention-days: 14
115+
116+
- name: Generate summary
117+
if: always()
118+
run: |
119+
echo "## WS Portfolio Feed Load Test Results" >> $GITHUB_STEP_SUMMARY
120+
echo "" >> $GITHUB_STEP_SUMMARY
121+
echo "**Test Configuration:**" >> $GITHUB_STEP_SUMMARY
122+
echo "- Concurrent Connections: 50" >> $GITHUB_STEP_SUMMARY
123+
echo "- Sustain Duration: 30s" >> $GITHUB_STEP_SUMMARY
124+
echo "- Auth Enabled: false" >> $GITHUB_STEP_SUMMARY
125+
echo "" >> $GITHUB_STEP_SUMMARY
126+
echo "**Purpose:** Periodically verifies WebSocket portfolio feed capacity and documents connection ceiling for planning." >> $GITHUB_STEP_SUMMARY
127+
26128
performance-test:
27129
runs-on: ubuntu-latest
28130
timeout-minutes: 15

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"audit:policy:update": "node scripts/check-npm-audit-baseline.mjs --write-baseline",
4242

4343
"test:chaos": "node scripts/chaos/kill-backend-mid-rebalance.mjs",
44+
"test:chaos:ws-load": "node scripts/chaos/ws-portfolio-feed-load-test.mjs",
4445

4546
"clean": "npm run clean:all",
4647
"clean:all": "rm -rf backend/dist frontend/dist contracts/target node_modules backend/node_modules frontend/node_modules"

0 commit comments

Comments
 (0)