at main 5.6 kB view raw
1#!/bin/bash 2# verify-export.sh - Verify local PLC export endpoint against multiple remotes 3# Usage: ./verify-export.sh [after_timestamp] [count] 4 5AFTER="${1:-}" 6COUNT="${2:-1000}" 7LOCAL_URL="http://localhost:8080/api/v1/plc/export" 8 9# Remote URLs (one per line: "name|url") 10REMOTES=( 11 "plc.directory|https://plc.directory/export" 12 "plc.wtf|https://plc.wtf/export" 13) 14 15echo "=== PLC Export Verification ===" 16echo "Count: $COUNT" 17if [ -n "$AFTER" ]; then 18 echo "After: $AFTER" 19else 20 echo "After: (none - from beginning)" 21fi 22echo "" 23 24# Build query parameters 25PARAMS="count=$COUNT" 26if [ -n "$AFTER" ]; then 27 PARAMS="${PARAMS}&after=${AFTER}" 28fi 29 30# Fetch from local 31echo "Fetching from local API..." 32echo "curl -s \"${LOCAL_URL}?${PARAMS}\"" 33LOCAL_DATA=$(curl -s "${LOCAL_URL}?${PARAMS}") 34LOCAL_COUNT=$(echo "$LOCAL_DATA" | wc -l | tr -d ' ') 35LOCAL_HASH=$(echo "$LOCAL_DATA" | shasum -a 256 | cut -d' ' -f1) 36 37echo " Operations: $LOCAL_COUNT" 38echo " Hash: $LOCAL_HASH" 39echo "" 40 41# Arrays to store remote data 42REMOTE_NAMES=() 43REMOTE_URLS=() 44REMOTE_DATA_ARR=() 45REMOTE_COUNT_ARR=() 46REMOTE_HASH_ARR=() 47 48# Fetch from all remotes 49for i in "${!REMOTES[@]}"; do 50 IFS='|' read -r name url <<< "${REMOTES[$i]}" 51 52 echo "Fetching from ${name}..." 53 echo "curl -s \"${url}?${PARAMS}\"" 54 55 data=$(curl -s "${url}?${PARAMS}") 56 count=$(echo "$data" | wc -l | tr -d ' ') 57 hash=$(echo "$data" | shasum -a 256 | cut -d' ' -f1) 58 59 REMOTE_NAMES+=("$name") 60 REMOTE_URLS+=("$url") 61 REMOTE_DATA_ARR+=("$data") 62 REMOTE_COUNT_ARR+=("$count") 63 REMOTE_HASH_ARR+=("$hash") 64 65 echo " Operations: $count" 66 echo " Hash: $hash" 67 echo "" 68done 69 70# Compare 71echo "=== COMPARISON ===" 72 73# Check local vs each remote 74ALL_MATCH=true 75MATCHES=() 76for i in "${!REMOTE_NAMES[@]}"; do 77 name="${REMOTE_NAMES[$i]}" 78 hash="${REMOTE_HASH_ARR[$i]}" 79 80 if [ "$LOCAL_HASH" = "$hash" ]; then 81 echo "Local vs ${name}: ✅ MATCH" 82 MATCHES+=("true") 83 else 84 echo "Local vs ${name}: ❌ MISMATCH" 85 MATCHES+=("false") 86 ALL_MATCH=false 87 fi 88done 89 90echo "" 91 92# Check remotes against each other 93REMOTES_MATCH=true 94if [ ${#REMOTE_NAMES[@]} -gt 1 ]; then 95 for ((i=0; i<${#REMOTE_NAMES[@]}-1; i++)); do 96 for ((j=i+1; j<${#REMOTE_NAMES[@]}; j++)); do 97 name1="${REMOTE_NAMES[$i]}" 98 name2="${REMOTE_NAMES[$j]}" 99 hash1="${REMOTE_HASH_ARR[$i]}" 100 hash2="${REMOTE_HASH_ARR[$j]}" 101 102 if [ "$hash1" = "$hash2" ]; then 103 echo "${name1} vs ${name2}: ✅ MATCH" 104 else 105 echo "${name1} vs ${name2}: ❌ MISMATCH" 106 REMOTES_MATCH=false 107 fi 108 done 109 done 110 echo "" 111fi 112 113if [ "$ALL_MATCH" = "true" ]; then 114 echo "🎉 ALL MATCH! All endpoints are in perfect sync! 🎯" 115 exit 0 116else 117 echo "❌ DISCREPANCIES DETECTED" 118 echo "" 119 120 # Show counts comparison 121 echo "=== OPERATION COUNTS ===" 122 echo "Local: $LOCAL_COUNT operations" 123 for i in "${!REMOTE_NAMES[@]}"; do 124 name="${REMOTE_NAMES[$i]}" 125 count="${REMOTE_COUNT_ARR[$i]}" 126 diff=$((count - LOCAL_COUNT)) 127 echo "${name}: ${count} operations (diff: ${diff})" 128 done 129 echo "" 130 131 # Sample operations from each source 132 echo "=== FIRST OPERATIONS ===" 133 echo "Local:" 134 echo "$LOCAL_DATA" | head -1 | jq -r '[.did, .cid, .createdAt] | @tsv' 2>/dev/null || echo "(parse error)" 135 echo "" 136 137 for i in "${!REMOTE_NAMES[@]}"; do 138 name="${REMOTE_NAMES[$i]}" 139 data="${REMOTE_DATA_ARR[$i]}" 140 echo "${name}:" 141 echo "$data" | head -1 | jq -r '[.did, .cid, .createdAt] | @tsv' 2>/dev/null || echo "(parse error)" 142 echo "" 143 done 144 145 echo "=== LAST OPERATIONS ===" 146 echo "Local:" 147 echo "$LOCAL_DATA" | tail -1 | jq -r '[.did, .cid, .createdAt] | @tsv' 2>/dev/null || echo "(parse error)" 148 echo "" 149 150 for i in "${!REMOTE_NAMES[@]}"; do 151 name="${REMOTE_NAMES[$i]}" 152 data="${REMOTE_DATA_ARR[$i]}" 153 echo "${name}:" 154 echo "$data" | tail -1 | jq -r '[.did, .cid, .createdAt] | @tsv' 2>/dev/null || echo "(parse error)" 155 echo "" 156 done 157 158 # Find first differences for mismatches 159 for i in "${!REMOTE_NAMES[@]}"; do 160 if [ "${MATCHES[$i]}" = "false" ]; then 161 name="${REMOTE_NAMES[$i]}" 162 data="${REMOTE_DATA_ARR[$i]}" 163 echo "=== FIRST DIFFERENCES (Local vs ${name}) ===" 164 diff <(echo "$LOCAL_DATA" | jq -r '.cid' 2>/dev/null | head -20) \ 165 <(echo "$data" | jq -r '.cid' 2>/dev/null | head -20) || true 166 echo "" 167 fi 168 done 169 170 # Check differences between remotes 171 if [ "$REMOTES_MATCH" = "false" ] && [ ${#REMOTE_NAMES[@]} -gt 1 ]; then 172 for ((i=0; i<${#REMOTE_NAMES[@]}-1; i++)); do 173 for ((j=i+1; j<${#REMOTE_NAMES[@]}; j++)); do 174 name1="${REMOTE_NAMES[$i]}" 175 name2="${REMOTE_NAMES[$j]}" 176 hash1="${REMOTE_HASH_ARR[$i]}" 177 hash2="${REMOTE_HASH_ARR[$j]}" 178 179 if [ "$hash1" != "$hash2" ]; then 180 data1="${REMOTE_DATA_ARR[$i]}" 181 data2="${REMOTE_DATA_ARR[$j]}" 182 echo "=== FIRST DIFFERENCES (${name1} vs ${name2}) ===" 183 diff <(echo "$data1" | jq -r '.cid' 2>/dev/null | head -20) \ 184 <(echo "$data2" | jq -r '.cid' 2>/dev/null | head -20) || true 185 echo "" 186 fi 187 done 188 done 189 fi 190 191 exit 1 192fi 193