Private/Send-Data.ps1

function Send-Data {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [VSphereConnectorState]$State,

        [Parameter(Mandatory = $true)]
        [VSphereConnectorConfiguration]$Config,

        [Parameter(Mandatory = $true)]
        [AllowEmptyCollection()]
        [VSphereHypervisorPayload[]]$Payload
    )

    try {
        if ($null -eq $Payload -or $Payload.Count -eq 0) {
            return
        }

        # Filter out events that were already sent
        $filteredPayloads = @(Get-PayloadEventsFiltered -Payloads $Payload -State $State)
        if ($filteredPayloads.Count -eq 0) {
            Write-CustomLog -Message "No events to send after filtering" -Severity 'INFO'
            return
        }

        $jwt = Get-Jwt -LoginHost $Config.NexthinkAPI.LoginFQDN -Target $Config.NexthinkAPI.WindowsCredentialEntry
        $hypervisorApiHost = $Config.NexthinkAPI.HostFQDN
        $endpointUrl = "https://$hypervisorApiHost/api/v1/hypervisor"

        $headers = @{
            'Content-Type'        = 'application/json'
            'Authorization'       = "Bearer $jwt"
        }

        $lastSentUtc = $null
        $anyFailed = $false

        foreach ($payloadItem in $filteredPayloads) {
            $payloadJson = ConvertTo-HypervisorPayloadJson -Payload $payloadItem
            $sentTimestampUtc = [DateTime]::UtcNow

            $attempt = 0
            $sentOk = $false
            while (-not $sentOk -and $attempt -lt 2) {
                $attempt++
                try {
                    $response = Invoke-WebRequestWithLogging -Uri $endpointUrl -Method 'POST' -Headers $headers -Body $payloadJson -UseBasicParsing
                    if ($null -ne $response -and $response.StatusCode -ge 200 -and $response.StatusCode -lt 300) {
                        $sentOk = $true
                    }
                    else {
                        throw "Hypervisor API returned unexpected status code '$($response.StatusCode)'"
                    }
                }
                catch {
                    if ($attempt -ge 2) {
                        $anyFailed = $true
                        break
                    }

                    Write-CustomLog -Message "Failed to send payload (attempt $attempt). Retrying once. Error=$($_.Exception.Message)" -Severity 'WARNING' -NoCache
                }
            }

            if (-not $sentOk) {
                Write-CustomLog -Message "Failed to send payload after retry. last_sent_utc will not be updated." -Severity 'ERROR' -NoCache
                continue
            }

            $lastSentUtc = $sentTimestampUtc.ToString('o')

            Write-CustomLog -Message "Successfully sent payload to Hypervisor API. Response code: $($response.StatusCode)" -Severity 'INFO' -NoCache
        }

        if ($anyFailed) {
            throw "One or more payloads failed to send to Hypervisor API. last_sent_utc was not updated."
        }

        if ($null -ne $State -and $null -ne $State.watermarks -and -not [string]::IsNullOrWhiteSpace($lastSentUtc)) {
            $State.watermarks.last_sent_utc = $lastSentUtc
            Save-State -State $State -Config $Config
        }
    }
    catch {
        Write-CustomLog -Message "Error sending data to Hypervisor API. Details: $($_.Exception.Message)" -Severity 'ERROR' -NoCache
        throw
    }
}