Invoke-PathCasHttpStressTemplate.ps1 3.03 KB
param(
    [string]$ApiBaseUrl = "http://localhost:5000",
    [string]$EndpointPath = "/api/internal/send-next-segment",
    [ValidateSet("GET","POST")]
    [string]$HttpMethod = "POST",
    [string]$RobotManufacturer = "HUAHENG",
    [string]$RobotSerialNumber = "1001",
    [int]$TotalRequests = 200,
    [int]$Concurrency = 20,
    [int]$TimeoutSeconds = 10
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

if ($TotalRequests -le 0) { throw "TotalRequests must be > 0" }
if ($Concurrency -le 0) { throw "Concurrency must be > 0" }
if ($Concurrency -gt $TotalRequests) { $Concurrency = $TotalRequests }

$query = "robotManufacturer=$([uri]::EscapeDataString($RobotManufacturer))&robotSerialNumber=$([uri]::EscapeDataString($RobotSerialNumber))"
$uri = "$ApiBaseUrl$EndpointPath?$query"

$handler = [System.Net.Http.HttpClientHandler]::new()
$client = [System.Net.Http.HttpClient]::new($handler)
$client.Timeout = [TimeSpan]::FromSeconds($TimeoutSeconds)

$semaphore = [System.Threading.SemaphoreSlim]::new($Concurrency, $Concurrency)
$success = 0L
$failure = 0L
$http4xx5xx = 0L
$exceptions = 0L

$tasks = New-Object System.Collections.Generic.List[System.Threading.Tasks.Task]
$sw = [System.Diagnostics.Stopwatch]::StartNew()

for ($i = 0; $i -lt $TotalRequests; $i++) {
    $null = $semaphore.Wait()

    $task = [System.Threading.Tasks.Task]::Run([Action]{
        try {
            if ($HttpMethod -eq "GET") {
                $resp = $client.GetAsync($uri).GetAwaiter().GetResult()
            }
            else {
                $resp = $client.PostAsync($uri, $null).GetAwaiter().GetResult()
            }

            if ($resp.IsSuccessStatusCode) {
                [System.Threading.Interlocked]::Increment([ref]$success) | Out-Null
            }
            else {
                [System.Threading.Interlocked]::Increment([ref]$failure) | Out-Null
                [System.Threading.Interlocked]::Increment([ref]$http4xx5xx) | Out-Null
            }
        }
        catch {
            [System.Threading.Interlocked]::Increment([ref]$failure) | Out-Null
            [System.Threading.Interlocked]::Increment([ref]$exceptions) | Out-Null
        }
        finally {
            $null = $semaphore.Release()
        }
    })

    $tasks.Add($task)
}

[System.Threading.Tasks.Task]::WaitAll($tasks.ToArray())
$sw.Stop()

$rps = if ($sw.Elapsed.TotalSeconds -gt 0) { [math]::Round($TotalRequests / $sw.Elapsed.TotalSeconds, 2) } else { 0 }

Write-Host "PathCAS HTTP Stress Template Result"
Write-Host "  Uri:              $uri"
Write-Host "  Method:           $HttpMethod"
Write-Host "  TotalRequests:    $TotalRequests"
Write-Host "  Concurrency:      $Concurrency"
Write-Host "  ElapsedMs:        $($sw.ElapsedMilliseconds)"
Write-Host "  RPS:              $rps"
Write-Host "  Success:          $success"
Write-Host "  Failure:          $failure"
Write-Host "  HttpNonSuccess:   $http4xx5xx"
Write-Host "  Exceptions:       $exceptions"
Write-Host ""
Write-Host "Then check service logs:"
Write-Host "  [PathCAS] ..."
Write-Host "  [PathCAS] HighConflictBackoff ..."