/api/program/echo

GET

Test 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.

💡 RAIDA Network Requirements

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)
⚡ Performance Characteristics

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
🎯 Use Cases

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

status string
Always "success" for this endpoint.
operation string
Always "echo".
raidas array
Array of 25 RAIDA server status objects (one per RAIDA). Each object contains:
index integer
RAIDA server index (0-24).
status string
Server status. Possible values:
  • "Ready" - Server responded successfully
  • "Timed Out" - Request exceeded timeout threshold
  • "Network Error" - No response received (connection failed)
  • "Invalid Response" - Server returned unexpected status code
network_latency_ms integer
Total round-trip time in milliseconds, including TCP handshake, request transmission, RAIDA processing, and response transmission. Typical range: 50-2000ms.
execution_time_ns integer
RAIDA server internal processing time in nanoseconds (time spent executing the echo command on the RAIDA server itself, excluding network latency).
total_available integer
Count of RAIDA servers with "Ready" status (0-25).
array_usable boolean
Indicates whether the RAIDA array meets the minimum quorum requirement. Returns 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
}
⚠️ Status Interpretation

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.