/api/program/echo
GETTest RAIDA network connectivity and health by sending echo requests to all 25 RAIDA servers in parallel.
Description
The `/api/program/echo` endpoint performs a health check on the entire RAIDA (Redundant Array of Independent Detection Agents) network by sending echo requests to all 25 RAIDA servers simultaneously. This endpoint provides detailed network latency, execution time, and status information for each RAIDA server.
The echo operation is executed in parallel using a thread pool, testing all 25 RAIDAs concurrently for optimal performance. The endpoint returns the status, network latency (in milliseconds), and internal processing time (in nanoseconds) for each RAIDA server.
The RAIDA network requires at least 13 out of 25 servers to be available for the array to be considered usable. This threshold ensures sufficient redundancy for CloudCoin authentication and operations.
- 13+ Ready: Array is usable (array_usable = true)
- <13 Ready: Array is unusable (array_usable = false)
This endpoint uses multi-threaded execution:
- Parallel Execution: All 25 RAIDAs tested simultaneously
- Typical Response Time: 1-2 seconds (network RTT + processing)
- Sequential Alternative: Would take ~25 seconds (1 second per RAIDA)
- Performance Gain: 20-25x faster than sequential execution
This endpoint is ideal for:
- Pre-flight checks before coin operations (Detect, POWN, Fix)
- Network health monitoring and diagnostics
- Identifying slow or offline RAIDA servers
- Measuring network latency to each RAIDA
- Verifying minimum quorum (13+ servers) is available
- Automated health check monitoring dashboards
Parameters
This endpoint does not require any parameters.
Response
Returns a JSON object with RAIDA network health status and detailed information for each of the 25 RAIDA servers.
Response Properties
- "Ready" - Server responded successfully
- "Timed Out" - Request exceeded timeout threshold
- "Network Error" - No response received (connection failed)
- "Invalid Response" - Server returned unexpected status code
true if total_available >= 13, otherwise false.Example Response (Healthy Network)
{
"status": "success",
"operation": "echo",
"raidas": [
{
"index": 0,
"status": "Ready",
"network_latency_ms": 245,
"execution_time_ns": 125340
},
{
"index": 1,
"status": "Ready",
"network_latency_ms": 312,
"execution_time_ns": 98765
},
{
"index": 2,
"status": "Ready",
"network_latency_ms": 189,
"execution_time_ns": 110234
},
// ... entries for RAIDAs 3-23 ...
{
"index": 24,
"status": "Ready",
"network_latency_ms": 278,
"execution_time_ns": 132567
}
],
"total_available": 25,
"array_usable": true
}
Example Response (Degraded Network)
{
"status": "success",
"operation": "echo",
"raidas": [
{
"index": 0,
"status": "Ready",
"network_latency_ms": 234,
"execution_time_ns": 115230
},
{
"index": 1,
"status": "Timed Out",
"network_latency_ms": 5000,
"execution_time_ns": 0
},
{
"index": 2,
"status": "Network Error",
"network_latency_ms": 0,
"execution_time_ns": 0
},
{
"index": 3,
"status": "Ready",
"network_latency_ms": 456,
"execution_time_ns": 142890
},
// ... more entries showing mix of Ready/Timed Out/Network Error ...
{
"index": 24,
"status": "Ready",
"network_latency_ms": 298,
"execution_time_ns": 128456
}
],
"total_available": 18,
"array_usable": true
}
Understanding RAIDA status codes:
- Ready: RAIDA responded with STATUS_NO_ERROR (0) or STATUS_SUCCESS (250)
- Timed Out: RAIDA did not respond within the timeout period (typically 5-10 seconds)
- Network Error: Connection failed or response not received (check firewall/DNS)
- Invalid Response: RAIDA returned an unexpected status code (rare, indicates server issue)
Examples
JavaScript (fetch)
const API_HOST = 'http://localhost:8080';
async function testRAIDANetwork() {
try {
const response = await fetch(`${API_HOST}/api/program/echo`);
const result = await response.json();
console.log('RAIDA Network Health Check:');
console.log(`Total Available: ${result.total_available}/25`);
console.log(`Array Usable: ${result.array_usable ? 'YES' : 'NO'}`);
console.log('');
// Group RAIDAs by status
const statusGroups = {
'Ready': [],
'Timed Out': [],
'Network Error': [],
'Invalid Response': []
};
result.raidas.forEach(raida => {
statusGroups[raida.status].push(raida);
});
// Display summary
console.log('Status Summary:');
Object.entries(statusGroups).forEach(([status, raidas]) => {
if (raidas.length > 0) {
console.log(` ${status}: ${raidas.length} RAIDAs`);
}
});
// Calculate average latency for ready RAIDAs
const readyRAIDAs = statusGroups['Ready'];
if (readyRAIDAs.length > 0) {
const avgLatency = readyRAIDAs.reduce((sum, r) =>
sum + r.network_latency_ms, 0) / readyRAIDAs.length;
console.log(` Average Latency: ${avgLatency.toFixed(2)} ms`);
}
// Warn if array is not usable
if (!result.array_usable) {
console.warn('WARNING: RAIDA array does not meet minimum quorum (13/25)!');
}
// Display slow RAIDAs (latency > 1000ms)
const slowRAIDAs = readyRAIDAs.filter(r => r.network_latency_ms > 1000);
if (slowRAIDAs.length > 0) {
console.log('\nSlow RAIDAs (>1000ms):');
slowRAIDAs.forEach(r => {
console.log(` RAIDA ${r.index}: ${r.network_latency_ms} ms`);
});
}
} catch (error) {
console.error('Error testing RAIDA network:', error);
}
}
testRAIDANetwork();
cURL
# Test RAIDA network health
curl -X GET "http://localhost:8080/api/program/echo"
# Pretty-print JSON output with jq
curl -X GET "http://localhost:8080/api/program/echo" | jq
# Check if array is usable
curl -s "http://localhost:8080/api/program/echo" | jq '.array_usable'
# Count ready RAIDAs
curl -s "http://localhost:8080/api/program/echo" | jq '.total_available'
# List all RAIDAs that are not ready
curl -s "http://localhost:8080/api/program/echo" | \
jq '.raidas[] | select(.status != "Ready") | {index, status, latency_ms: .network_latency_ms}'
# Calculate average latency for ready RAIDAs
curl -s "http://localhost:8080/api/program/echo" | \
jq '[.raidas[] | select(.status == "Ready") | .network_latency_ms] | add / length'
Go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
const ApiHost = "http://localhost:8080"
type RAIDAStatus struct {
Index int `json:"index"`
Status string `json:"status"`
NetworkLatencyMs int `json:"network_latency_ms"`
ExecutionTimeNs int64 `json:"execution_time_ns"`
}
type EchoResponse struct {
Status string `json:"status"`
Operation string `json:"operation"`
RAIDAs []RAIDAStatus `json:"raidas"`
TotalAvailable int `json:"total_available"`
ArrayUsable bool `json:"array_usable"`
}
func main() {
fmt.Println("Testing RAIDA Network Health...")
startTime := time.Now()
resp, err := http.Get(fmt.Sprintf("%s/api/program/echo", ApiHost))
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result EchoResponse
if err := json.Unmarshal(body, &result); err != nil {
fmt.Printf("Error parsing JSON: %v\n", err)
return
}
elapsed := time.Since(startTime)
fmt.Printf("Request completed in %v\n\n", elapsed)
// Display summary
fmt.Printf("RAIDA Network Status:\n")
fmt.Printf(" Total Available: %d/25\n", result.TotalAvailable)
fmt.Printf(" Array Usable: %v\n", result.ArrayUsable)
if !result.ArrayUsable {
fmt.Println(" ⚠️ WARNING: Array does not meet minimum quorum!")
}
fmt.Println()
// Count by status
statusCounts := make(map[string]int)
var totalLatency int
var readyCount int
for _, raida := range result.RAIDAs {
statusCounts[raida.Status]++
if raida.Status == "Ready" {
totalLatency += raida.NetworkLatencyMs
readyCount++
}
}
// Display status breakdown
fmt.Println("Status Breakdown:")
for status, count := range statusCounts {
fmt.Printf(" %s: %d\n", status, count)
}
// Calculate and display average latency
if readyCount > 0 {
avgLatency := float64(totalLatency) / float64(readyCount)
fmt.Printf("\nAverage Network Latency: %.2f ms\n", avgLatency)
}
// List slow or problematic RAIDAs
fmt.Println("\nProblematic RAIDAs:")
hasProblems := false
for _, raida := range result.RAIDAs {
if raida.Status != "Ready" {
fmt.Printf(" RAIDA %d: %s\n", raida.Index, raida.Status)
hasProblems = true
} else if raida.NetworkLatencyMs > 1000 {
fmt.Printf(" RAIDA %d: Slow (%d ms)\n", raida.Index, raida.NetworkLatencyMs)
hasProblems = true
}
}
if !hasProblems {
fmt.Println(" None - All RAIDAs healthy!")
}
}
Implementation Details
Timeout Configuration
The echo operation uses a dynamic timeout calculation:
- Base timeout: 5000ms (5 seconds)
- Minimum timeout: 3000ms (3 seconds)
- Maximum timeout: 15000ms (15 seconds)
Thread Pool Execution
The endpoint uses a dedicated thread pool with 25 worker threads (one per RAIDA):
- Each RAIDA request runs in its own thread
- No shared state between threads during execution
- Results collected independently per RAIDA
- Socket operations are thread-safe within each context
Network Latency Measurement
The network_latency_ms field measures the complete round-trip time, including:
- TCP handshake (SYN, SYN-ACK, ACK) - typically 50-200ms
- Request transmission time
- RAIDA server processing time
- Response transmission time
- Network latency (RTT)
Response Status Determination
The status field is determined by the following logic:
if (timed_out) {
status = "Timed Out";
} else if (!received) {
status = "Network Error";
} else if (status == STATUS_NO_ERROR || status == STATUS_SUCCESS) {
status = "Ready";
} else {
status = "Invalid Response";
}
Related Endpoints
/api/program/status
Get program version information, currently active wallet, and server time.
/api/raida/version
Get detailed version information from each RAIDA server including software version and protocol support.