Skip to content

Commit af5d8b7

Browse files
committed
Fix AI review comments for benchmark PR
1 parent 95347b6 commit af5d8b7

2 files changed

Lines changed: 36 additions & 19 deletions

File tree

.github/workflows/benchmark.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@ jobs:
2525
run: |
2626
npm run dev -w apps/api &
2727
# Wait for server to start
28-
sleep 5
28+
echo "Waiting for API server..."
29+
for i in {1..30}; do
30+
if curl -s http://localhost:3000/health > /dev/null; then
31+
echo "Server is up!"
32+
break
33+
fi
34+
sleep 1
35+
done
2936
env:
3037
STRIPE_SECRET_KEY: sk_test_benchmark
3138
PORT: 3000
@@ -34,6 +41,7 @@ jobs:
3441
run: |
3542
export BENCHMARK_DURATION=2
3643
export BENCHMARK_CONNECTIONS=5
44+
export BENCHMARK_AUTH_TOKEN=$(node -e "const jwt = require('./apps/api/node_modules/jsonwebtoken'); console.log(jwt.sign({ sub: 'admin_123', role: 'admin' }, process.env.JWT_SECRET || 'fallback_secret', { expiresIn: '1h' }))")
3745
npm run benchmark
3846
env:
3947
CI: true

benchmarks/run.mjs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ import { fileURLToPath } from 'url';
77
const __filename = fileURLToPath(import.meta.url);
88
const __dirname = path.dirname(__filename);
99

10-
// Load env config
11-
dotenv.config({ path: path.join(__dirname, '.env.benchmark') });
10+
// Load env config (fallback to standard .env if .env.benchmark doesn't exist)
11+
if (fs.existsSync && require('fs').existsSync(path.join(__dirname, '.env.benchmark'))) {
12+
dotenv.config({ path: path.join(__dirname, '.env.benchmark') });
13+
} else {
14+
dotenv.config();
15+
}
1216

13-
const HOST = process.env.BENCHMARK_TARGET_HOST || 'http://localhost:3000';
17+
const HOST = process.env.BENCHMARK_TARGET_HOST || 'http://localhost:4000';
1418
const TOKEN = process.env.BENCHMARK_AUTH_TOKEN || 'test_token';
1519
const DURATION = parseInt(process.env.BENCHMARK_DURATION || '5', 10);
1620
const CONNECTIONS = parseInt(process.env.BENCHMARK_CONNECTIONS || '10', 10);
@@ -19,17 +23,18 @@ const THRESHOLDS_PATH = path.join(__dirname, 'thresholds.json');
1923

2024
const endpoints = [
2125
{ name: 'Health Check', path: '/health', method: 'GET' },
26+
{ name: 'Auth Login', path: '/api/auth/login', method: 'POST', body: JSON.stringify({ email: 'test@example.com', password: 'test' }) },
2227
{ name: 'Get Users', path: '/api/users', method: 'GET', auth: true },
2328
{ name: 'Get Jobs', path: '/api/jobs', method: 'GET' },
29+
{ name: 'Post Job', path: '/api/jobs', method: 'POST', auth: true, body: JSON.stringify({ title: 'Benchmark Test Job', description: 'Test', budget: 100 }) },
30+
{ name: 'Get Proposals', path: '/api/proposals', method: 'GET', auth: true },
31+
{ name: 'Get Payments', path: '/api/payments', method: 'GET', auth: true },
32+
{ name: 'Get Reviews', path: '/api/reviews', method: 'GET', auth: true },
33+
{ name: 'Get Messages', path: '/api/messages', method: 'GET', auth: true },
34+
{ name: 'Get Notifications', path: '/api/notifications', method: 'GET', auth: true },
35+
{ name: 'Get Uploads', path: '/api/uploads', method: 'GET', auth: true },
2436
{ name: 'Search', path: '/api/search?q=test', method: 'GET' },
25-
{ name: 'Admin Metrics', path: '/api/admin/metrics', method: 'GET', auth: true },
26-
{
27-
name: 'Post Job',
28-
path: '/api/jobs',
29-
method: 'POST',
30-
auth: true,
31-
body: JSON.stringify({ title: 'Benchmark Test Job', description: 'Test', budget: 100 })
32-
}
37+
{ name: 'Admin Metrics', path: '/api/admin/metrics', method: 'GET', auth: true }
3338
];
3439

3540
async function runBenchmark(endpoint) {
@@ -45,6 +50,9 @@ async function runBenchmark(endpoint) {
4550
};
4651

4752
if (endpoint.auth) {
53+
if (TOKEN === 'test_token' || !TOKEN) {
54+
return reject(new Error(`BENCHMARK_AUTH_TOKEN must be set to a valid token for authenticated endpoint: ${endpoint.name}`));
55+
}
4856
opts.headers['Authorization'] = `Bearer ${TOKEN}`;
4957
}
5058

@@ -76,20 +84,21 @@ async function main() {
7684
try {
7785
const result = await runBenchmark(endpoint);
7886

79-
const p50 = result.latency.p50;
80-
const p95 = result.latency.p95;
81-
const p99 = result.latency.p99;
82-
const rps = result.requests.average;
83-
const errorRate = (result.errors / result.requests.total) * 100 || 0;
87+
const p50 = result.latency.p50 || null;
88+
const p95 = result.latency.p97_5 || null;
89+
const p99 = result.latency.p99 || null;
90+
const rps = result.requests.average || 0;
91+
const totalErrors = result.errors + (result.non2xx || 0);
92+
const errorRate = (totalErrors / result.requests.total) * 100 || 0;
8493
// We estimate TTFB by using min latency or a proxy, but autocannon latency is effectively TTFB to full response.
85-
const ttfb = result.latency.min;
94+
const ttfb = result.latency.min || null;
8695

8796
const data = {
8897
name: endpoint.name,
8998
path: endpoint.path,
9099
method: endpoint.method,
91100
p50, p95, p99, rps, errorRate, ttfb,
92-
passed: p99 <= thresholds.maxP99LatencyMs && errorRate <= thresholds.maxErrorRatePercent
101+
passed: p99 <= thresholds.maxP99LatencyMs && errorRate <= thresholds.maxErrorRatePercent && rps >= (thresholds.minRps || 0)
93102
};
94103

95104
results.push(data);

0 commit comments

Comments
 (0)