|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# Test script to verify cache fills to 1000 entries properly |
| 4 | +# Tests the improved parallelism handling with reduced batch size and timeouts |
| 5 | + |
| 6 | +# Configuration |
| 7 | +BASE_URL="${BASE_URL:-http://localhost:3005}" |
| 8 | +TARGET_SIZE=1000 |
| 9 | +BATCH_SIZE=20 |
| 10 | + |
| 11 | +# Determine API paths based on URL |
| 12 | +if [[ "$BASE_URL" == *"devstore.rerum.io"* ]] || [[ "$BASE_URL" == *"store.rerum.io"* ]]; then |
| 13 | + # Production/dev server paths |
| 14 | + CACHE_STATS_PATH="/v1/api/cache/stats" |
| 15 | + CACHE_CLEAR_PATH="/v1/api/cache/clear" |
| 16 | + API_QUERY_PATH="/v1/api/query" |
| 17 | +else |
| 18 | + # Local server paths |
| 19 | + CACHE_STATS_PATH="/cache/stats" |
| 20 | + CACHE_CLEAR_PATH="/cache/clear" |
| 21 | + API_QUERY_PATH="/api/query" |
| 22 | +fi |
| 23 | + |
| 24 | +# Colors for output |
| 25 | +RED='\033[0;31m' |
| 26 | +GREEN='\033[0;32m' |
| 27 | +YELLOW='\033[1;33m' |
| 28 | +BLUE='\033[0;34m' |
| 29 | +NC='\033[0m' # No Color |
| 30 | + |
| 31 | +echo "═══════════════════════════════════════════════════════════════════════" |
| 32 | +echo " RERUM Cache Fill Test" |
| 33 | +echo "═══════════════════════════════════════════════════════════════════════" |
| 34 | +echo "" |
| 35 | +echo "Testing cache fill to $TARGET_SIZE entries with improved parallelism handling" |
| 36 | +echo "Server: $BASE_URL" |
| 37 | +echo "Batch size: $BATCH_SIZE requests per batch" |
| 38 | +echo "" |
| 39 | + |
| 40 | +# Check server connectivity |
| 41 | +echo -n "[INFO] Checking server connectivity... " |
| 42 | +if ! curl -sf "$BASE_URL" > /dev/null 2>&1; then |
| 43 | + echo -e "${RED}FAIL${NC}" |
| 44 | + echo "Server at $BASE_URL is not responding" |
| 45 | + exit 1 |
| 46 | +fi |
| 47 | +echo -e "${GREEN}OK${NC}" |
| 48 | + |
| 49 | +# Clear cache |
| 50 | +echo -n "[INFO] Clearing cache... " |
| 51 | +if [[ "$BASE_URL" == *"devstore.rerum.io"* ]] || [[ "$BASE_URL" == *"store.rerum.io"* ]]; then |
| 52 | + # Production/dev servers may be load-balanced with multiple instances |
| 53 | + # Clear multiple times to hit all instances |
| 54 | + for i in {1..5}; do |
| 55 | + curl -sf -X POST "$BASE_URL$CACHE_CLEAR_PATH" > /dev/null 2>&1 |
| 56 | + done |
| 57 | + sleep 1 |
| 58 | + echo -e "${YELLOW}WARN${NC}" |
| 59 | + echo "[INFO] Note: Server appears to be load-balanced across multiple instances" |
| 60 | + echo "[INFO] Cache clear may not affect all instances - continuing with test" |
| 61 | +else |
| 62 | + # Local server - single instance |
| 63 | + curl -sf -X POST "$BASE_URL$CACHE_CLEAR_PATH" > /dev/null 2>&1 |
| 64 | + sleep 1 |
| 65 | + initial_stats=$(curl -sf "$BASE_URL$CACHE_STATS_PATH") |
| 66 | + initial_length=$(echo "$initial_stats" | grep -o '"length":[0-9]*' | cut -d: -f2) |
| 67 | + if [ "$initial_length" = "0" ]; then |
| 68 | + echo -e "${GREEN}OK${NC} (length: 0)" |
| 69 | + else |
| 70 | + echo -e "${YELLOW}WARN${NC} (length: $initial_length)" |
| 71 | + fi |
| 72 | +fi |
| 73 | + |
| 74 | +# Fill cache function with improved error handling |
| 75 | +SUCCESSFUL_REQUESTS=0 |
| 76 | +FAILED_REQUESTS=0 |
| 77 | +TIMEOUT_REQUESTS=0 |
| 78 | + |
| 79 | +fill_cache() { |
| 80 | + local target_size=$1 |
| 81 | + local successful_requests=0 |
| 82 | + local failed_requests=0 |
| 83 | + local timeout_requests=0 |
| 84 | + |
| 85 | + echo "" |
| 86 | + echo "▓▓▓ Filling Cache to $target_size Entries ▓▓▓" |
| 87 | + echo "" |
| 88 | + |
| 89 | + for ((i=0; i<target_size; i+=BATCH_SIZE)); do |
| 90 | + local batch_end=$((i + BATCH_SIZE)) |
| 91 | + if [ $batch_end -gt $target_size ]; then |
| 92 | + batch_end=$target_size |
| 93 | + fi |
| 94 | + |
| 95 | + # Clear temp file for this batch |
| 96 | + rm -f /tmp/cache_fill_results_$$.tmp |
| 97 | + |
| 98 | + # Send batch of requests in parallel |
| 99 | + for ((j=i; j<batch_end; j++)); do |
| 100 | + ( |
| 101 | + # Use different query types that return actual data |
| 102 | + # Cycle through known query patterns that return results |
| 103 | + queries=( |
| 104 | + '{"type":"Annotation"}' |
| 105 | + '{"@type":"Annotation"}' |
| 106 | + '{"@type":"Gloss"}' |
| 107 | + '{"@type":"Person"}' |
| 108 | + '{"type":"Person"}' |
| 109 | + '{"type":"Manifest"}' |
| 110 | + '{"type":"Canvas"}' |
| 111 | + '{"type":"AnnotationPage"}' |
| 112 | + ) |
| 113 | + |
| 114 | + # Select query based on index to create variety |
| 115 | + query_index=$((j % 8)) |
| 116 | + query_body="${queries[$query_index]}" |
| 117 | + |
| 118 | + # Add a unique parameter to each query to ensure they're cached separately |
| 119 | + # Use the request number to make each query unique |
| 120 | + query_body=$(echo "$query_body" | sed "s/}/, \"_test_id\": $j}/") |
| 121 | + |
| 122 | + response=$(curl -s \ |
| 123 | + --max-time 30 \ |
| 124 | + --connect-timeout 10 \ |
| 125 | + -w "\n%{http_code}" \ |
| 126 | + -X POST \ |
| 127 | + -H "Content-Type: application/json" \ |
| 128 | + -d "$query_body" \ |
| 129 | + "$BASE_URL$API_QUERY_PATH" 2>&1) |
| 130 | + |
| 131 | + exit_code=$? |
| 132 | + http_code=$(echo "$response" | tail -1) |
| 133 | + |
| 134 | + if [ $exit_code -eq 28 ]; then |
| 135 | + # Timeout |
| 136 | + echo "timeout" >> /tmp/cache_fill_results_$$.tmp |
| 137 | + elif [ $exit_code -ne 0 ]; then |
| 138 | + # Network error |
| 139 | + echo "fail:network_error_$exit_code" >> /tmp/cache_fill_results_$$.tmp |
| 140 | + elif [ "$http_code" = "200" ]; then |
| 141 | + # Success |
| 142 | + echo "success" >> /tmp/cache_fill_results_$$.tmp |
| 143 | + else |
| 144 | + # HTTP error |
| 145 | + echo "fail:http_$http_code" >> /tmp/cache_fill_results_$$.tmp |
| 146 | + fi |
| 147 | + ) & |
| 148 | + done |
| 149 | + |
| 150 | + # Wait for all requests in this batch to complete |
| 151 | + wait |
| 152 | + |
| 153 | + # Count results from temp file |
| 154 | + batch_success=0 |
| 155 | + batch_timeout=0 |
| 156 | + batch_fail=0 |
| 157 | + if [ -f /tmp/cache_fill_results_$$.tmp ]; then |
| 158 | + batch_success=$(grep -c "^success$" /tmp/cache_fill_results_$$.tmp 2>/dev/null) |
| 159 | + batch_timeout=$(grep -c "^timeout$" /tmp/cache_fill_results_$$.tmp 2>/dev/null) |
| 160 | + batch_fail=$(grep -c "^fail:" /tmp/cache_fill_results_$$.tmp 2>/dev/null) |
| 161 | + # grep -c returns 0 if no matches, so these are safe |
| 162 | + batch_success=${batch_success:-0} |
| 163 | + batch_timeout=${batch_timeout:-0} |
| 164 | + batch_fail=${batch_fail:-0} |
| 165 | + rm /tmp/cache_fill_results_$$.tmp |
| 166 | + fi |
| 167 | + |
| 168 | + successful_requests=$((successful_requests + batch_success)) |
| 169 | + timeout_requests=$((timeout_requests + batch_timeout)) |
| 170 | + failed_requests=$((failed_requests + batch_fail)) |
| 171 | + |
| 172 | + completed=$batch_end |
| 173 | + local pct=$((completed * 100 / target_size)) |
| 174 | + echo -ne "\r Progress: $completed/$target_size requests sent (${pct}%) | Success: $successful_requests | Timeout: $timeout_requests | Failed: $failed_requests " |
| 175 | + |
| 176 | + # Add small delay between batches to prevent overwhelming the server |
| 177 | + sleep 0.5 |
| 178 | + done |
| 179 | + echo "" |
| 180 | + |
| 181 | + # Summary |
| 182 | + echo "" |
| 183 | + echo "▓▓▓ Request Statistics ▓▓▓" |
| 184 | + echo "" |
| 185 | + echo " Total requests sent: $target_size" |
| 186 | + echo -e " Successful (200 OK): ${GREEN}$successful_requests${NC}" |
| 187 | + if [ $timeout_requests -gt 0 ]; then |
| 188 | + echo " Timeouts: $timeout_requests" |
| 189 | + else |
| 190 | + echo " Timeouts: $timeout_requests" |
| 191 | + fi |
| 192 | + if [ $failed_requests -gt 0 ]; then |
| 193 | + echo -e " Failed: ${RED}$failed_requests${NC}" |
| 194 | + else |
| 195 | + echo " Failed: $failed_requests" |
| 196 | + fi |
| 197 | + echo "" |
| 198 | + |
| 199 | + # Store in global variables for later use |
| 200 | + SUCCESSFUL_REQUESTS=$successful_requests |
| 201 | + FAILED_REQUESTS=$failed_requests |
| 202 | + TIMEOUT_REQUESTS=$timeout_requests |
| 203 | +} |
| 204 | + |
| 205 | +# Fill the cache |
| 206 | +fill_cache $TARGET_SIZE |
| 207 | + |
| 208 | +# Get final cache stats |
| 209 | +echo "[INFO] Getting final cache statistics..." |
| 210 | +final_stats=$(curl -sf "$BASE_URL$CACHE_STATS_PATH") |
| 211 | +final_length=$(echo "$final_stats" | grep -o '"length":[0-9]*' | cut -d: -f2) |
| 212 | +total_sets=$(echo "$final_stats" | grep -o '"sets":[0-9]*' | cut -d: -f2) |
| 213 | +total_hits=$(echo "$final_stats" | grep -o '"hits":[0-9]*' | cut -d: -f2) |
| 214 | +total_misses=$(echo "$final_stats" | grep -o '"misses":[0-9]*' | cut -d: -f2) |
| 215 | +total_evictions=$(echo "$final_stats" | grep -o '"evictions":[0-9]*' | cut -d: -f2) |
| 216 | + |
| 217 | +echo "" |
| 218 | +echo "▓▓▓ Final Cache Statistics ▓▓▓" |
| 219 | +echo "" |
| 220 | +echo " Cache entries: $final_length" |
| 221 | +echo " Total sets: $total_sets" |
| 222 | +echo " Total hits: $total_hits" |
| 223 | +echo " Total misses: $total_misses" |
| 224 | +echo " Total evictions: $total_evictions" |
| 225 | +echo "" |
| 226 | + |
| 227 | +# Analyze results |
| 228 | +echo "▓▓▓ Analysis ▓▓▓" |
| 229 | +echo "" |
| 230 | + |
| 231 | +success=true |
| 232 | + |
| 233 | +# Check request success rate first (most important) |
| 234 | +success_rate=$((SUCCESSFUL_REQUESTS * 100 / TARGET_SIZE)) |
| 235 | +if [ $success_rate -ge 95 ]; then |
| 236 | + echo -e "${GREEN}✓${NC} Excellent request success rate: ${success_rate}% (${SUCCESSFUL_REQUESTS}/${TARGET_SIZE})" |
| 237 | +elif [ $success_rate -ge 90 ]; then |
| 238 | + echo -e "${YELLOW}⚠${NC} Good request success rate: ${success_rate}% (${SUCCESSFUL_REQUESTS}/${TARGET_SIZE})" |
| 239 | +else |
| 240 | + echo -e "${RED}✗${NC} Poor request success rate: ${success_rate}% (${SUCCESSFUL_REQUESTS}/${TARGET_SIZE})" |
| 241 | + success=false |
| 242 | +fi |
| 243 | + |
| 244 | +# Check timeouts |
| 245 | +if [ $TIMEOUT_REQUESTS -eq 0 ]; then |
| 246 | + echo -e "${GREEN}✓${NC} No timeouts" |
| 247 | +elif [ $TIMEOUT_REQUESTS -lt $((TARGET_SIZE / 20)) ]; then |
| 248 | + echo -e "${GREEN}✓${NC} Very few timeouts: $TIMEOUT_REQUESTS" |
| 249 | +else |
| 250 | + echo -e "${YELLOW}⚠${NC} Some timeouts: $TIMEOUT_REQUESTS" |
| 251 | +fi |
| 252 | + |
| 253 | +# Check failures |
| 254 | +if [ $FAILED_REQUESTS -eq 0 ]; then |
| 255 | + echo -e "${GREEN}✓${NC} No failed requests" |
| 256 | +elif [ $FAILED_REQUESTS -lt $((TARGET_SIZE / 20)) ]; then |
| 257 | + echo -e "${GREEN}✓${NC} Very few failures: $FAILED_REQUESTS" |
| 258 | +else |
| 259 | + echo -e "${YELLOW}⚠${NC} Some failures: $FAILED_REQUESTS" |
| 260 | +fi |
| 261 | + |
| 262 | +# Check if cache filled (but this depends on query results) |
| 263 | +if [ "$final_length" -ge 990 ]; then |
| 264 | + echo -e "${GREEN}✓${NC} Cache filled successfully (${final_length}/${TARGET_SIZE} entries)" |
| 265 | +elif [ "$final_length" -ge 300 ]; then |
| 266 | + echo -e "${YELLOW}ℹ${NC} Cache has ${final_length} entries (many queries returned empty results)" |
| 267 | + echo " Note: Cache only stores non-empty array responses by design" |
| 268 | +else |
| 269 | + echo -e "${RED}✗${NC} Cache fill lower than expected (${final_length}/${TARGET_SIZE} entries)" |
| 270 | + success=false |
| 271 | +fi |
| 272 | + |
| 273 | +# Diagnose issues if any |
| 274 | +if [ "$success" != "true" ]; then |
| 275 | + echo "" |
| 276 | + echo "▓▓▓ Diagnosis ▓▓▓" |
| 277 | + echo "" |
| 278 | + |
| 279 | + if [ $TIMEOUT_REQUESTS -gt $((TARGET_SIZE / 10)) ]; then |
| 280 | + echo -e "${YELLOW}⚠${NC} High number of timeouts detected" |
| 281 | + echo " Recommendation: Increase --max-time or reduce batch size" |
| 282 | + fi |
| 283 | + |
| 284 | + if [ $FAILED_REQUESTS -gt $((TARGET_SIZE / 10)) ]; then |
| 285 | + echo -e "${YELLOW}⚠${NC} High number of failed requests" |
| 286 | + echo " Recommendation: Check server logs for errors" |
| 287 | + fi |
| 288 | + |
| 289 | + # Check if responses weren't cached (might not be arrays) |
| 290 | + if [ -n "$total_sets" ] && [ -n "$SUCCESSFUL_REQUESTS" ] && [ "$total_sets" -lt $((SUCCESSFUL_REQUESTS - 50)) ]; then |
| 291 | + echo -e "${YELLOW}⚠${NC} Many successful responses were NOT cached" |
| 292 | + echo " Reason: Responses may not be arrays (cache only stores array responses)" |
| 293 | + echo " Sets: $total_sets vs Successful requests: $SUCCESSFUL_REQUESTS" |
| 294 | + fi |
| 295 | + |
| 296 | + if [ -n "$total_evictions" ] && [ "$total_evictions" -gt 0 ]; then |
| 297 | + echo -e "${YELLOW}⚠${NC} Cache evictions occurred during fill" |
| 298 | + echo " Evictions: $total_evictions" |
| 299 | + echo " Reason: Cache may be full or entries timing out" |
| 300 | + fi |
| 301 | +fi |
| 302 | + |
| 303 | +echo "" |
| 304 | +echo "═══════════════════════════════════════════════════════════════════════" |
| 305 | + |
| 306 | +if [ "$success" = "true" ]; then |
| 307 | + echo -e "${GREEN}TEST PASSED${NC}" |
| 308 | + exit 0 |
| 309 | +else |
| 310 | + echo -e "${YELLOW}TEST COMPLETED WITH WARNINGS${NC}" |
| 311 | + exit 1 |
| 312 | +fi |
0 commit comments