tangled
alpha
login
or
join now
atscan.net
/
plcbundle
A Transparent and Verifiable Way to Sync the AT Protocol's PLC Directory
14
fork
atom
overview
issues
2
pulls
pipelines
sync status as json
tree.fail
3 months ago
2fc8370e
40ffa60d
+31
-61
1 changed file
expand all
collapse all
unified
split
cmd
plcbundle
server.go
+31
-61
cmd/plcbundle/server.go
···
170
170
fmt.Fprintf(w, "plcbundle v%s | https://github.com/atscan/plcbundle\n", version)
171
171
}
172
172
173
173
-
// handleSync returns sync status and mempool info
173
173
+
// handleSync returns sync status and mempool info as JSON
174
174
func handleSync(w http.ResponseWriter, mgr *bundle.Manager) {
175
175
-
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
175
175
+
w.Header().Set("Content-Type", "application/json")
176
176
w.Header().Set("Access-Control-Allow-Origin", "*")
177
177
178
178
index := mgr.GetIndex()
179
179
-
stats := index.GetStats()
180
180
-
bundleCount := stats["bundle_count"].(int)
179
179
+
indexStats := index.GetStats()
180
180
+
mempoolStats := mgr.GetMempoolStats()
181
181
182
182
-
fmt.Fprintf(w, "Sync Status\n")
183
183
-
fmt.Fprintf(w, "═══════════\n\n")
184
184
-
185
185
-
// Bundle info
186
186
-
fmt.Fprintf(w, "Bundles\n")
187
187
-
fmt.Fprintf(w, "───────\n")
188
188
-
fmt.Fprintf(w, "Count: %d\n", bundleCount)
189
189
-
190
190
-
if bundleCount > 0 {
191
191
-
firstBundle := stats["first_bundle"].(int)
192
192
-
lastBundle := stats["last_bundle"].(int)
193
193
-
totalSize := stats["total_size"].(int64)
182
182
+
// Build response
183
183
+
response := map[string]interface{}{
184
184
+
"bundles": map[string]interface{}{
185
185
+
"count": indexStats["bundle_count"],
186
186
+
"total_size": indexStats["total_size"],
187
187
+
"updated_at": indexStats["updated_at"],
188
188
+
},
189
189
+
"mempool": mempoolStats,
190
190
+
}
194
191
195
195
-
fmt.Fprintf(w, "Range: %06d - %06d\n", firstBundle, lastBundle)
196
196
-
fmt.Fprintf(w, "Total size: %.2f MB\n", float64(totalSize)/(1024*1024))
197
197
-
fmt.Fprintf(w, "Last updated: %s\n", stats["updated_at"].(time.Time).Format(time.RFC3339))
192
192
+
// Add bundle range if bundles exist
193
193
+
if bundleCount, ok := indexStats["bundle_count"].(int); ok && bundleCount > 0 {
194
194
+
response["bundles"].(map[string]interface{})["first_bundle"] = indexStats["first_bundle"]
195
195
+
response["bundles"].(map[string]interface{})["last_bundle"] = indexStats["last_bundle"]
196
196
+
response["bundles"].(map[string]interface{})["start_time"] = indexStats["start_time"]
197
197
+
response["bundles"].(map[string]interface{})["end_time"] = indexStats["end_time"]
198
198
199
199
-
if gaps, ok := stats["gaps"].(int); ok && gaps > 0 {
200
200
-
fmt.Fprintf(w, "⚠ Gaps: %d missing bundles\n", gaps)
199
199
+
if gaps, ok := indexStats["gaps"].(int); ok {
200
200
+
response["bundles"].(map[string]interface{})["gaps"] = gaps
201
201
}
202
202
}
203
203
204
204
-
// Mempool info
205
205
-
mempoolStats := mgr.GetMempoolStats()
206
206
-
count := mempoolStats["count"].(int)
207
207
-
targetBundle := mempoolStats["target_bundle"].(int)
208
208
-
canCreate := mempoolStats["can_create_bundle"].(bool)
209
209
-
minTimestamp := mempoolStats["min_timestamp"].(time.Time)
210
210
-
validated := mempoolStats["validated"].(bool)
211
211
-
212
212
-
fmt.Fprintf(w, "\nMempool\n")
213
213
-
fmt.Fprintf(w, "───────\n")
214
214
-
fmt.Fprintf(w, "Target bundle: %06d\n", targetBundle)
215
215
-
fmt.Fprintf(w, "Operations: %d / %d\n", count, bundle.BUNDLE_SIZE)
216
216
-
fmt.Fprintf(w, "Can create bundle: %v\n", canCreate)
217
217
-
fmt.Fprintf(w, "Min timestamp: %s\n", minTimestamp.Format(time.RFC3339))
218
218
-
fmt.Fprintf(w, "Validated: %v\n", validated)
219
219
-
220
220
-
if count > 0 {
204
204
+
// Calculate mempool progress percentage
205
205
+
if count, ok := mempoolStats["count"].(int); ok {
221
206
progress := float64(count) / float64(bundle.BUNDLE_SIZE) * 100
222
222
-
fmt.Fprintf(w, "Progress: %.1f%%\n", progress)
223
223
-
224
224
-
// Progress bar
225
225
-
barWidth := 50
226
226
-
filled := int(float64(barWidth) * float64(count) / float64(bundle.BUNDLE_SIZE))
227
227
-
if filled > barWidth {
228
228
-
filled = barWidth
229
229
-
}
230
230
-
bar := strings.Repeat("█", filled) + strings.Repeat("░", barWidth-filled)
231
231
-
fmt.Fprintf(w, "\n[%s]\n\n", bar)
207
207
+
response["mempool"].(map[string]interface{})["progress_percent"] = progress
208
208
+
response["mempool"].(map[string]interface{})["bundle_size"] = bundle.BUNDLE_SIZE
209
209
+
}
232
210
233
233
-
if sizeBytes, ok := mempoolStats["size_bytes"].(int); ok {
234
234
-
fmt.Fprintf(w, "Size: %.2f KB\n", float64(sizeBytes)/1024)
235
235
-
}
236
236
-
if firstTime, ok := mempoolStats["first_time"].(time.Time); ok {
237
237
-
fmt.Fprintf(w, "First operation: %s\n", firstTime.Format(time.RFC3339))
238
238
-
}
239
239
-
if lastTime, ok := mempoolStats["last_time"].(time.Time); ok {
240
240
-
fmt.Fprintf(w, "Last operation: %s\n", lastTime.Format(time.RFC3339))
241
241
-
}
242
242
-
} else {
243
243
-
fmt.Fprintf(w, "\n(empty)\n")
211
211
+
data, err := json.MarshalIndent(response, "", " ")
212
212
+
if err != nil {
213
213
+
http.Error(w, "Failed to marshal sync status", http.StatusInternalServerError)
214
214
+
return
244
215
}
245
216
246
246
-
fmt.Fprintf(w, "\nEndpoints:\n")
247
247
-
fmt.Fprintf(w, " /sync/mempool - JSONL stream of mempool operations\n")
217
217
+
w.Write(data)
248
218
}
249
219
250
220
// handleSyncMempool streams mempool operations as JSONL