mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 01:01:09 +02:00
- Route all AI workloads (Ollama, STT, TTS, Image Gen) to GPU server (192.168.178.11) via LAN instead of host.docker.internal - Upgrade default model to gemma3:12b and max concurrent to 5 - Add daily signup limit service (MAX_DAILY_SIGNUPS env var) - Add GET /api/v1/auth/signup-status public endpoint - Add k6 load test suite (web-apps, auth, sync-websocket, ollama) - Add capacity planning documentation - Fix: add eslint-config to sveltekit-base and calendar Dockerfiles Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
2.1 KiB
JavaScript
84 lines
2.1 KiB
JavaScript
/* eslint-disable no-undef, no-console, @typescript-eslint/no-unused-vars */
|
|
import ws from 'k6/ws';
|
|
import { check, sleep } from 'k6';
|
|
import { Rate, Counter, Trend } from 'k6/metrics';
|
|
|
|
const errorRate = new Rate('errors');
|
|
const messagesReceived = new Counter('ws_messages_received');
|
|
const messagesSent = new Counter('ws_messages_sent');
|
|
const connectTime = new Trend('ws_connect_time', true);
|
|
|
|
const SYNC_URL = __ENV.SYNC_URL || 'ws://localhost:3050';
|
|
|
|
export const options = {
|
|
stages: [
|
|
{ duration: '30s', target: 10 },
|
|
{ duration: '3m', target: 30 },
|
|
{ duration: '30s', target: 0 },
|
|
],
|
|
thresholds: {
|
|
errors: ['rate<0.10'],
|
|
ws_connect_time: ['p(95)<1000'],
|
|
},
|
|
};
|
|
|
|
export default function () {
|
|
const url = `${SYNC_URL}/ws`;
|
|
|
|
const startTime = Date.now();
|
|
const res = ws.connect(url, {}, function (socket) {
|
|
const connected = Date.now() - startTime;
|
|
connectTime.add(connected);
|
|
|
|
socket.on('open', () => {
|
|
// Send a sync handshake (collection subscription)
|
|
const handshake = JSON.stringify({
|
|
type: 'subscribe',
|
|
collections: ['tasks', 'events', 'contacts'],
|
|
userId: `loadtest-vu-${__VU}`,
|
|
lastSyncTimestamp: new Date(Date.now() - 60000).toISOString(),
|
|
});
|
|
socket.send(handshake);
|
|
messagesSent.add(1);
|
|
});
|
|
|
|
socket.on('message', (data) => {
|
|
messagesReceived.add(1);
|
|
|
|
// Parse and validate sync messages
|
|
try {
|
|
const msg = JSON.parse(data);
|
|
check(msg, {
|
|
'has type field': (m) => m.type !== undefined,
|
|
});
|
|
} catch (_) {
|
|
// Binary or non-JSON message
|
|
}
|
|
});
|
|
|
|
socket.on('error', (e) => {
|
|
errorRate.add(true);
|
|
console.error(`WS error VU ${__VU}: ${e.error()}`);
|
|
});
|
|
|
|
// Keep connection alive for 10-30 seconds (simulates real user session)
|
|
const sessionDuration = Math.random() * 20 + 10;
|
|
|
|
// Send periodic sync pings
|
|
const pingInterval = setInterval(() => {
|
|
socket.send(JSON.stringify({ type: 'ping' }));
|
|
messagesSent.add(1);
|
|
}, 5000);
|
|
|
|
sleep(sessionDuration);
|
|
clearInterval(pingInterval);
|
|
socket.close();
|
|
});
|
|
|
|
const ok = check(res, {
|
|
'WS connection status is 101': (r) => r && r.status === 101,
|
|
});
|
|
errorRate.add(!ok);
|
|
|
|
sleep(Math.random() * 2 + 1);
|
|
}
|