|
| 1 | +#!/bin/bash |
| 2 | +# Tiered Memory Recovery Test Script |
| 3 | +# |
| 4 | +# This script tests system recovery when storage consumption exceeds physical memory. |
| 5 | +# It uses a small physical memory limit (256MB) and imports a larger dataset. |
| 6 | +# The embedding index is disabled to focus on storage/tiered memory behavior. |
| 7 | +# |
| 8 | +# Usage: ./scripts/test_tiered_memory_recovery.sh [max_entities] |
| 9 | +# max_entities: Number of entities to import (default: 50000 - should exceed 256MB) |
| 10 | + |
| 11 | +set -e |
| 12 | + |
| 13 | +# Configuration |
| 14 | +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 15 | +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" |
| 16 | +WIKIDATA_FILE="${WIKIDATA_FILE:-/mnt/micron/wikidata20160104.json}" |
| 17 | +MAX_ENTITIES="${1:-50000}" # Default increased to ensure we exceed 256MB |
| 18 | +STORAGE_BASE="/tmp/tiered_memory_test" |
| 19 | +IMPORT_CONFIG_FILE="$STORAGE_BASE/import_config.yaml" |
| 20 | +RECOVERY_CONFIG_FILE="$STORAGE_BASE/recovery_config.yaml" |
| 21 | +PORT=7201 # Different port to avoid conflict |
| 22 | +VERIFICATION_LOG="$STORAGE_BASE/verification.log" |
| 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 | +CYAN='\033[0;36m' |
| 30 | +NC='\033[0m' # No Color |
| 31 | + |
| 32 | +log_info() { |
| 33 | + echo -e "${BLUE}[INFO]${NC} $1" |
| 34 | +} |
| 35 | + |
| 36 | +log_success() { |
| 37 | + echo -e "${GREEN}[SUCCESS]${NC} $1" |
| 38 | +} |
| 39 | + |
| 40 | +log_warn() { |
| 41 | + echo -e "${YELLOW}[WARN]${NC} $1" |
| 42 | +} |
| 43 | + |
| 44 | +log_error() { |
| 45 | + echo -e "${RED}[ERROR]${NC} $1" |
| 46 | +} |
| 47 | + |
| 48 | +log_phase() { |
| 49 | + echo "" |
| 50 | + echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" |
| 51 | + echo -e "${CYAN} $1${NC}" |
| 52 | + echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" |
| 53 | + echo "" |
| 54 | +} |
| 55 | + |
| 56 | +# Check prerequisites |
| 57 | +check_prerequisites() { |
| 58 | + log_info "Checking prerequisites..." |
| 59 | + |
| 60 | + if [[ ! -f "$WIKIDATA_FILE" ]]; then |
| 61 | + log_error "Wikidata dump file not found: $WIKIDATA_FILE" |
| 62 | + log_info "Set WIKIDATA_FILE environment variable to the correct path" |
| 63 | + exit 1 |
| 64 | + fi |
| 65 | + |
| 66 | + if ! command -v cargo &> /dev/null; then |
| 67 | + log_error "cargo not found. Please install Rust." |
| 68 | + exit 1 |
| 69 | + fi |
| 70 | + |
| 71 | + # Check for the binary (Debug build) |
| 72 | + if [[ ! -f "$PROJECT_DIR/target/debug/wikidata_cli" ]]; then |
| 73 | + log_warn "Debug binary not found at $PROJECT_DIR/target/debug/wikidata_cli" |
| 74 | + log_info "Please run: cargo build --bin wikidata_cli --no-default-features --features cpu_optimized" |
| 75 | + # We don't exit here, allowing the script to try using cargo run if needed or user to build |
| 76 | + fi |
| 77 | + |
| 78 | + log_success "Prerequisites check passed" |
| 79 | +} |
| 80 | + |
| 81 | +# Clean up previous test data |
| 82 | +cleanup() { |
| 83 | + log_info "Cleaning up previous test data..." |
| 84 | + rm -rf "$STORAGE_BASE" |
| 85 | + mkdir -p "$STORAGE_BASE/backup" |
| 86 | + mkdir -p "$STORAGE_BASE/wal" |
| 87 | + mkdir -p "$STORAGE_BASE/raft" |
| 88 | + mkdir -p "$STORAGE_BASE/undo" |
| 89 | + log_success "Cleanup complete" |
| 90 | +} |
| 91 | + |
| 92 | +# Create configuration files with tight memory limit |
| 93 | +create_configs() { |
| 94 | + log_info "Creating configuration files with 256MB physical memory limit..." |
| 95 | + |
| 96 | + # Import config |
| 97 | + cat > "$IMPORT_CONFIG_FILE" << EOF |
| 98 | +server_addr: 127.0.0.1:$PORT |
| 99 | +group_name: TieredMemoryTest |
| 100 | +meta_members: |
| 101 | + - 127.0.0.1:$PORT |
| 102 | +storage: |
| 103 | + chunk_count: 16 |
| 104 | + total_size: "64GB" |
| 105 | + backup_storage: "$STORAGE_BASE/backup" |
| 106 | + wal_storage: "$STORAGE_BASE/wal" |
| 107 | + raft_storage: "$STORAGE_BASE/raft" |
| 108 | + undo_log_storage: "$STORAGE_BASE/undo" |
| 109 | + enable_recovery: false |
| 110 | + services: |
| 111 | + - Cell |
| 112 | + - Transaction |
| 113 | + - RangedIndexer |
| 114 | + - Query |
| 115 | + index_enabled: true |
| 116 | + tiered_config: |
| 117 | + threshold: 0.8 |
| 118 | + physical_memory_limit: "256MB" |
| 119 | +EOF |
| 120 | + |
| 121 | + # Recovery config |
| 122 | + cat > "$RECOVERY_CONFIG_FILE" << EOF |
| 123 | +server_addr: 127.0.0.1:$PORT |
| 124 | +group_name: TieredMemoryTest |
| 125 | +meta_members: |
| 126 | + - 127.0.0.1:$PORT |
| 127 | +storage: |
| 128 | + chunk_count: 16 |
| 129 | + total_size: "64GB" |
| 130 | + backup_storage: "$STORAGE_BASE/backup" |
| 131 | + wal_storage: "$STORAGE_BASE/wal" |
| 132 | + raft_storage: "$STORAGE_BASE/raft" |
| 133 | + undo_log_storage: "$STORAGE_BASE/undo" |
| 134 | + enable_recovery: true |
| 135 | + services: |
| 136 | + - Cell |
| 137 | + - Transaction |
| 138 | + - RangedIndexer |
| 139 | + - Query |
| 140 | + index_enabled: true |
| 141 | + tiered_config: |
| 142 | + threshold: 0.8 |
| 143 | + physical_memory_limit: "256MB" |
| 144 | +EOF |
| 145 | + |
| 146 | + log_success "Configuration files created" |
| 147 | +} |
| 148 | + |
| 149 | +# Phase 1: Import data |
| 150 | +run_import() { |
| 151 | + log_phase "PHASE 1: Importing $MAX_ENTITIES entities (Memory Limit: 256MB)" |
| 152 | + |
| 153 | + cd "$PROJECT_DIR" |
| 154 | + |
| 155 | + log_info "Starting import with:" |
| 156 | + log_info " • No Embedding Indexing (--no-embedding)" |
| 157 | + log_info " • Batch size: 100" |
| 158 | + log_info " • Workers: 4" |
| 159 | + log_info " • Max entities: $MAX_ENTITIES" |
| 160 | + echo "" |
| 161 | + |
| 162 | + # Run the import |
| 163 | + # We use RUST_LOG to see memory usage logs if available, or just standard info |
| 164 | + RUST_LOG=morpheus::apps::wikidata=info,info "$PROJECT_DIR/target/debug/wikidata_cli" import \ |
| 165 | + "$WIKIDATA_FILE" \ |
| 166 | + --config "$IMPORT_CONFIG_FILE" \ |
| 167 | + --max-entities "$MAX_ENTITIES" \ |
| 168 | + --batch-size 100 \ |
| 169 | + --workers 4 \ |
| 170 | + --no-embedding 2>&1 | tee "$STORAGE_BASE/import.log" |
| 171 | + |
| 172 | + local exit_code=$? |
| 173 | + if [[ $exit_code -ne 0 ]]; then |
| 174 | + log_error "Import failed with exit code $exit_code" |
| 175 | + exit 1 |
| 176 | + fi |
| 177 | + |
| 178 | + log_success "Import phase completed successfully" |
| 179 | + |
| 180 | + # Wait a bit for wal flush |
| 181 | + log_info "Waiting for WAL flush..." |
| 182 | + sleep 5 |
| 183 | +} |
| 184 | + |
| 185 | +# Phase 2: Recovery Verification |
| 186 | +run_recovery_test() { |
| 187 | + log_phase "PHASE 2: Testing Recovery (Simulating restart)" |
| 188 | + |
| 189 | + cd "$PROJECT_DIR" |
| 190 | + |
| 191 | + log_info "Starting recovery verification..." |
| 192 | + log_info "Attempting to query entities from the recovered store..." |
| 193 | + |
| 194 | + # We use 'import-and-query' or just 'import' script usually just does import. |
| 195 | + # To test recovery, run a query command against the RECOVERY config. |
| 196 | + # But wikidata_cli 'query' command might be useful here. |
| 197 | + # However, to simulate 'recovery', we just need to start the server and read data. |
| 198 | + # We can use 'import-and-query' with 0 entities to just start up and query? |
| 199 | + # Or better, we can use a dedicated 'query' command or 'server' command if available. |
| 200 | + # Looking at wikidata_cli, it has 'Import', 'ImportAndQuery', 'Query'. |
| 201 | + # 'Query' seems appropriate. |
| 202 | + |
| 203 | + # Let's query for a known entity (e.g., Q42) to verify it exists. |
| 204 | + # Assuming Q42 is within the first 50k entities. |
| 205 | + |
| 206 | + # Enable pipefail to catch errors in piped commands |
| 207 | + set -o pipefail |
| 208 | + |
| 209 | + RUST_LOG=info "$PROJECT_DIR/target/debug/wikidata_cli" query \ |
| 210 | + --config "$RECOVERY_CONFIG_FILE" \ |
| 211 | + entity --entity-id "Q42" 2>&1 | tee -a "$VERIFICATION_LOG" |
| 212 | + |
| 213 | + local exit_code=$? |
| 214 | + if [[ $exit_code -ne 0 ]]; then |
| 215 | + log_error "Recovery verification failed! Server might have failed to start or find data." |
| 216 | + exit 1 |
| 217 | + fi |
| 218 | + |
| 219 | + log_success "Recovery verification successful!" |
| 220 | +} |
| 221 | + |
| 222 | +# Main execution flow |
| 223 | +main() { |
| 224 | + check_prerequisites |
| 225 | + cleanup |
| 226 | + create_configs |
| 227 | + run_import |
| 228 | + run_recovery_test |
| 229 | +} |
| 230 | + |
| 231 | +main |
0 commit comments