#!/bin/bash # Load Test Script for Build Streaming # Simulates concurrent builds with SSE clients to verify event delivery # # Usage: # ./scripts/load-test-builds.sh [num_concurrent] [duration_seconds] # # Example: # ./scripts/load-test-builds.sh 10 60 # 10 concurrent streams for 60 seconds set -euo pipefail # Configuration API_URL="${RDEV_API_URL:-https://rdev.masq-ops.orchard9.ai}" API_KEY="${RDEV_API_KEY:?RDEV_API_KEY environment variable required}" NUM_CONCURRENT="${1:-5}" DURATION="${2:-30}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } # Track metrics EVENTS_RECEIVED=0 CONNECTIONS_OPENED=0 CONNECTIONS_FAILED=0 STREAM_PIDS=() # Cleanup on exit cleanup() { log_info "Cleaning up..." for pid in "${STREAM_PIDS[@]}"; do kill "$pid" 2>/dev/null || true done } trap cleanup EXIT # Simulate an SSE client that counts events run_sse_client() { local client_id="$1" local stream_id="load-test-stream-$client_id" local events_file="/tmp/load-test-events-$client_id.txt" echo "0" > "$events_file" # Connect and count events curl -s -N \ -H "X-API-Key: ${API_KEY}" \ -H "Accept: text/event-stream" \ "${API_URL}/projects/load-test-project/events?stream_id=${stream_id}" 2>/dev/null | \ while IFS= read -r line; do if [[ "$line" == "data:"* ]]; then # Increment event count count=$(<"$events_file") echo "$((count + 1))" > "$events_file" fi done & echo $! } # Publish events to simulate build activity publish_events() { local num_events="$1" local stream_id="$2" for i in $(seq 1 "$num_events"); do # Use curl to trigger some activity (this is a simulation) # In real usage, events come from BuildExecutor sleep 0.1 done } echo "" echo "==========================================" echo " Build Streaming Load Test" echo "==========================================" echo "" echo " Concurrent clients: $NUM_CONCURRENT" echo " Test duration: ${DURATION}s" echo " API URL: $API_URL" echo "" # Check API health first log_info "Checking API health..." if ! curl -sf "${API_URL}/health" > /dev/null 2>&1; then log_error "API health check failed" exit 1 fi log_success "API is healthy" echo "" # Start concurrent SSE clients log_info "Starting $NUM_CONCURRENT SSE clients..." for i in $(seq 1 "$NUM_CONCURRENT"); do pid=$(run_sse_client "$i") if [[ -n "$pid" ]]; then STREAM_PIDS+=("$pid") CONNECTIONS_OPENED=$((CONNECTIONS_OPENED + 1)) else CONNECTIONS_FAILED=$((CONNECTIONS_FAILED + 1)) fi done log_success "Started $CONNECTIONS_OPENED clients ($CONNECTIONS_FAILED failed)" echo "" # Wait for test duration log_info "Running load test for ${DURATION}s..." sleep "$DURATION" # Collect results log_info "Collecting results..." total_events=0 for i in $(seq 1 "$NUM_CONCURRENT"); do events_file="/tmp/load-test-events-$i.txt" if [[ -f "$events_file" ]]; then count=$(<"$events_file") total_events=$((total_events + count)) rm -f "$events_file" fi done # Kill remaining clients for pid in "${STREAM_PIDS[@]}"; do kill "$pid" 2>/dev/null || true done STREAM_PIDS=() echo "" echo "==========================================" echo " Load Test Results" echo "==========================================" echo "" echo " Duration: ${DURATION}s" echo " Clients started: $CONNECTIONS_OPENED" echo " Clients failed: $CONNECTIONS_FAILED" echo " Total events received: $total_events" echo " Events per second: $(echo "scale=2; $total_events / $DURATION" | bc 2>/dev/null || echo "N/A")" echo " Events per client: $(echo "scale=2; $total_events / $CONNECTIONS_OPENED" | bc 2>/dev/null || echo "N/A")" echo "" # Check for memory usage if running locally if command -v ps > /dev/null 2>&1; then log_info "Memory usage check:" echo " Run 'kubectl top pods -n rdev' to check rdev-api memory" fi echo "" if [[ $CONNECTIONS_FAILED -eq 0 ]] && [[ $total_events -gt 0 ]]; then log_success "Load test completed successfully" exit 0 else log_error "Load test completed with issues" exit 1 fi