wip
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