"Resulting JSON is truncated" error with Pode and Pode.Web for API and WEB UI
Describe the Bug
Similar to https://github.com/Badgerati/Pode.Web/issues/605. When combining Pode.Web with Pode to provide API and Web Front-End, I get:
WARNING: Resulting JSON is truncated as serialization has exceeded the set depth of 10.
Then the state.json is empty.
If I remove all Add-PodeWebPage calls, I do not get this error.
Steps To Reproduce
Import-Module Pode
Import-Module Pode.Web
Start-PodeServer {
Class AuthHeaders {
[String] static $token = 'TOKEN'
static [Hashtable] GetAuthHeaders() {
return [Hashtable] @{
"Authorization" = ("Bearer {0}" -f [AuthHeaders]::token)
"Content-type" = "application/json"
}
}
}
Class AppVeyorJob {
[ValidateSet("Group1", "Group2", 'Group3', 'Group4', 'TotGroup', 'LTSGroup')] [String] $Name
[String[]] $Appliances = [String[]]::new(4)
[String] $JobID
[String] $JobUrl
[ValidateSet("Stopped", "Running", 'Completed', 'Maintenance')] [String] $State = 'Stopped'
[DateTime] $Start
[DateTime] $End
AppVeyorJob ($Name) {
$this.Name = $Name
}
AppVeyorJob ([String]$Name, [String]$JobID, [Uri]$JobUrl, [String]$State) {
# If the evaluation is false, throw error
if (-not $JobUrl -eq 'INTERNAL' -and -not [String]::IsNullOrEmpty($JobUrl.AbsolutePath) -and -not $JobUrl.AbsolutePath.StartsWith("/api/projects/org/")) {
Throw "JobURI is not a valid URI. Must start with /api/projects/org/."
}
# $this.Appliances = $state:CurrentConfig.Groups.$Name
$this.Name = $Name
$this.JobID = $JobID
$this.JobUrl = $JobUrl
$this.State = $State
}
[AppVeyorJob] SetAppliances ([String[]]$Appliances) {
For ($i = 0; $i -lt $Appliances.Count; $i++) {
$this.Appliances[$i] = $Appliances[$i]
}
return $this
}
[Boolean] IsRunning() {
if ([String]::IsNullOrEmpty($this.JobURL)) {
Throw "JobURL is null. Cannot check if job is still running."
}
elseif ($this.JobUrl -eq 'INTERNAL') {
$this.State = "Running"
return $true
}
else {
try {
$_currentState = Invoke-RestMethod -Uri $this.JobUrl -Method Get -Headers ([AuthHeaders]::GetAuthHeaders())
}
catch {
Write-Host "Error: $($_.Exception.Message)"
return $false
}
if ($_currentState.build.status -eq 'Running') {
$this.State = "Running"
$this.Start = $_currentState.build.started
return $true
}
else {
$this.State = "Stopped"
$this.Start = $_currentState.build.started
$this.End = $_currentState.build.updated
return $false
}
}
}
static [AppVeyorJob[]] Init() {
$GroupNames = "Group1", "Group2", 'Group3', 'Group4', 'TotGroup', 'LTSGroup'
$Collection = @()
ForEach ($_group in $GroupNames) {
$Collection += [AppVeyorJob]::new($_group)
}
return $Collection
}
}
# Create static class to return network interface(s) index to bind Pode service to based on connected state and those with an IPv4 address
Class NetInterface {
static [Int[]] GetAvailableAdapterIndex() {
$FoundAdapterIndexes = Get-NetAdapter | Where-Object {
($_.MediaConnectionState -eq 'Connected' -or $_.ifOperStatus -eq 'Connected') -and
$_.ifDesc -notmatch 'Loopback' -and
$_.ifDesc -notmatch 'VPN' -and
$_.ifDesc -notmatch 'TAP'
} | Select-Object ifIndex -Unique -ExpandProperty ifIndex
if ($FoundAdapterIndexes.Count -eq 0) {
Throw "No network interfaces found with a connected state."
}
else {
return $FoundAdapterIndexes
}
}
}
# request logging
# New-PodeLoggingMethod -Terminal -Batch 10 -BatchTimeout 10 | Enable-PodeRequestLogging
New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging -Levels Error, Warning, Informational, Verbose
Set-PodeSecurityAccessControl -Methods 'GET', 'POST', 'PATCH' -Origin '*' -Headers 'Content-Type'
$PodeBasePath = Join-Path 'C:' 'Temp' 'pode'
$BaseUploadPath = Join-Path 'C:' 'Temp' 'pode' 'uploads'
"Setting PodeStateConfigFileLocation" | Out-Default
# Location where the Pode server state variables are stored
$PodeStateConfigFileLocation = (Join-Path $PodeBasePath 'state.json')
$cache:PodeStateConfig = $PodeStateConfigFileLocation
"Setting UploadFileDirectoryLocation" | Out-Default
# File upload location, which is for uploading pester unit test result documents
$cache:UploadFileDirectory = $BaseUploadPath
Get-PodeConfig
"Attempting to restore pode state" | Out-Default
# attempt to re-initialise the state (will do nothing if the file doesn't exist)
Restore-PodeState -Path $cache:PodeStateConfig
# create the shared variable
if ($null -eq $state:CurrentJobs) {
# $Appliances = Set-PodeState -name 'Appliances' -value @{} -Scope Scope0
Set-PodeState -Name 'CurrentJobs' -Value ([AppVeyorJob]::Init())
$null = Save-PodeState -Path $cache:PodeStateConfig
}
# Need to loop through each group and check if the job is still running
else {
# Need to re-create the class objects after restoring the state from the JSON file
For ($j = 0; $j -lt $state:CurrentJobs.Count; $j++) {
$state:CurrentJobs[$j] = [AppVeyorJob]::new($state:CurrentJobs[$j].Name, $state:CurrentJobs[$j].JobID, $state:CurrentJobs[$j].JobUrl, $state:CurrentJobs[$j].State)
if ($state:CurrentJobs[$j].State -eq "Running" -and -not [String]::IsNullOrEmpty($state:CurrentJobs[$j].JobUrl)) {
# check if the job is still running
$Result = $state:CurrentJobs[$j] -ne "Maintenance" ? $state:CurrentJobs[$j].IsRunning() : @{ status = 'Maintenance' }
"Job still running: {0}" -f $Result | Out-Host
if ($Result.status -eq "running") {
"Job {0} is still running." -f $state:CurrentJobs[$j].JobID | Out-Host
$state:CurrentJobs[$j].State = "Running"
}
elseif ($Result.status -ne 'Maintenance') {
"Job {0} is no longer running. Clearing from tracking." -f $state:CurrentJobs[$j].JobID | Out-Host
$state:CurrentJobs[$j].State = "Stopped"
$state:CurrentJobs[$j].Appliances.Clear()
$state:CurrentJobs[$j].JobID = $null
$state:CurrentJobs[$j].JobUrl = $null
}
}
elseif ($state:CurrentJobs[$j].State -eq "Running" -and [String]::IsNullOrEmpty($state:CurrentJobs[$j].JobUrl)) {
"Job {0} is no longer running as JobURL is null. Clearing from tracking." -f $state:CurrentJobs[$j].JobId | Out-Host
$state:CurrentJobs[$j].State = "Stopped"
$state:CurrentJobs[$j].JobID = $null
}
}
$null = Save-PodeState -Path $cache:PodeStateConfig
}
# Check to make sure the cert has not expired
$Cert = Get-ChildItem Cert:\LocalMachine\My | ? { $_.Subject -match $env:COMPUTERNAME -and $_.Issuer -match "CA" -and -not $_.Archived }
if ($null -eq $Cert) {
Thorw "No available web certificates found."
}
# Attempt to renew the cert if expired
if ([datetime]::Now -ge $Cert.NotAfter) {
certreq -enroll -machine -q -PolicyServer * -cert $Cert.Thumbprint renew reusekeys
}
ForEach ($ip in ([Netinterface]::GetAvailableAdapterIndex() | % { Get-NetIPAddress -InterfaceIndex $_ }).IPAddress) {
"Binding to $ip" | Out-Default
Add-PodeEndpoint -Address $ip -Port 8443 -Protocol Https -CertificateStoreLocation LocalMachine -CertificateStoreName My -CertificateThumbprint $Cert.Thumbprint
}
# Return the appliance configuration JSON object
Add-PodeRoute -Method Get -Path '/api/currentConfig' -ScriptBlock {
Lock-PodeObject -ScriptBlock {
Write-PodeJsonResponse -StatusCode 200 -Value $state:CurrentConfig
}
}
# API to check out an available group and assign a job to it. If JobURL is "INTERNAL", the job is not checked with Appveyor API
# POST /api/jobs/checkOut
# Request body:
# {
# "JobID": "1.10.10",
# "JobURL": "https://ci.appveyor.com/api/projects/org/proj/build/1.10.10"
# }
#
# Response body:
# {
# "Name": "Group1",
# "Appliances": [
# "Appliance1",
# "Appliance2",
# "Appliance3",
# "Appliance4"
# ],
# "JobID": "1.10.10",
# "JobURL": "https://ci.appveyor.com/api/projects/org/proj/build/1.10.10"
# "State": "Running"
# }
#
# Error response body with HTTP400:
# {
# "ErrorID": "Invalid_Request_Body",
# "ErrorDescription": "The missing JobID and JobURL in request body."
# }
#
# Error response body with HTTP400:
# {
# "ErrorID": "Invalid_Request_Body",
# "ErrorDescription": "The missing JobID in request body."
# }
#
# Error response body with HTTP400:
# {
# "ErrorID": "Invalid_Request_Body",
# "ErrorDescription": "The missing JobURL in request body."
# }
#
#
# Error response body with HTTP406:
# {
# "ErrorID": "No_Available_Slots",
# "ErrorDescription": "No available slots."
# }
#
Add-PodeRoute -Method Post -Path '/api/jobs/checkOut' -ScriptBlock {
$WebEvent.Data | Out-PodeHost
$RequestBody = $WebEvent.Data
if ($RequestBody.Count -eq 0 -or $null -eq $RequestBody) {
Write-PodeJsonResponse -StatusCode 400 -Value @{ ErrorID = 'Invalid_Request_Body'; ErrorDescription = "The missing JobID and JobURL in request body." }
}
elseif (-not $RequestBody['JobID']) {
Write-PodeJsonResponse -StatusCode 400 -Value @{ ErrorID = 'Invalid_Request_Body'; ErrorDescription = "The missing JobID in request body." }
}
elseif (-not $RequestBody['JobURL']) {
Write-PodeJsonResponse -StatusCode 400 -Value @{ ErrorID = 'Invalid_Request_Body'; ErrorDescription = "The missing JobURL in request body." }
}
else {
$JobIdRegex = [regex]::new("^\d{1,3}\.\d+(\.\d+){0,2}$")
"JobID: {0}" -f $RequestBody['JobID'] | Out-Host
# Will also need to have a validation on the JobID format
if (-not $JobIdRegex.Match($RequestBody['JobID']).Success) {
Write-PodeJsonResponse -StatusCode 400 -Value @{ ErrorID = 'Invalid_JobID_Format'; ErrorDescription = "JobID format is invalid. Expected format: 1.10, 1.10.100, 1.10.1234.5678." }
}
else {
$FoundDuplicate = $state:CurrentJobs.GetEnumerator() | ? { $_['JobID'] -eq $RequestBody['JobID'] }
if ($FoundDuplicate) {
Write-PodeJsonResponse -StatusCode 409 -Value @{ ErrorID = 'Duplicate_JobID'; ErrorDescription = "JobID already exists." }
}
else {
"No dupe found." | Out-Host
# again, ensure we're thread safe
Lock-PodeObject -ScriptBlock {
"Locked." | Out-Host
# $state:CurrentJobs.GetEnumerator() | ? { $_.State -eq 'Stopped' } | Select -First 1 | Out-Host
[Version]$JobVersion = $RequestBody['JobID']
[Version]$LtsVersion = $state:CurrentConfig.WhatIsLts
[Version]$TotVersion = $state:CurrentConfig.WhatIsTot
# Need to enhance this to handle LTS and TOT groups based on JobID (which should be a version string)
if ($JobVersion.Major -eq $LtsVersion.Major -and $JobVersion.Minor -eq $LtsVersion.Minor) {
$Result = $state:CurrentJobs.GetEnumerator() | ? { $_.Name -eq 'LTSGroup' -and $_.State -eq 'Stopped' }
}
elseif ($JobVersion.Major -eq $TotVersion.Major -and $JobVersion.Minor -eq $TotVersion.Minor) {
$Result = $state:CurrentJobs.GetEnumerator() | ? { $_.Name -eq 'TotGroup' -and $_.State -eq 'Stopped' }
}
else {
$Result = $state:CurrentJobs.GetEnumerator() | ? { $_.State -eq 'Stopped' } | Select -First 1
}
if ($null -eq $Result -or $WebEvent.Query['TestError'] -eq "True") {
Write-PodeJsonResponse -StatusCode 406 -Value @{ ErrorID = 'No_Available_Slots'; ErrorDescription = "No available slots." }
}
else {
"Setting job to Group '{0}'." -f $Result.Name | Out-Host
$Result.JobID = $RequestBody['JobID']
$Result.JobUrl = $RequestBody['JobURL']
$Result.State = "Running"
$GroupID = $Result.Name
"Setting appliances within tracking object" | Out-Host
$Result.SetAppliances($state:CurrentConfig.Groups.${GroupID})
# Do not monitor an INTERNAL job
if ($Result.JobUrl -ne 'INTERNAL') {
"Job not 'INTERNAL', getting AppVeyor job state." | Out-Host
# Need to connect back to AppVeyors API to get the job start time
$JobStatus = Invoke-RestMethod -Uri $Result.JobUrl -Method Get -Headers ([AuthHeaders]::GetAuthHeaders())
$Result.Start = $JobStatus.build.started
}
else {
"Job 'INTERNAL'." | Out-Host
$Result.Start = [datetime]::now
}
"Return result." | Out-Host
# Will need to add logic here to validate the job is still running by using Invoke-RestMethod to $Result.JobUrl
Write-PodeJsonResponse -Value $Result
# Need to have Pode to continuously check the job status as a scheduled task
# Invoke-PodeTask -Name 'MonitorJob' -ArgumentList @{ GroupID = $Result.Name }
"Saving StateConfig." | Out-Host
$null = Save-PodeState -Path $cache:PodeStateConfig
}
}
"Done." | Out-Host
}
}
}
}
Add-PodeRoute -Method Get -Path '/api/ping' -ScriptBlock {
Write-PodeJsonResponse -Value @{ 'value' = 'pong' }
}
# WEB UI FRONT-END
Use-PodeWebTemplates -Title 'Example' -Theme Dark
# # Use-PodeWebTemplates -Title 'Example' -Theme Dark -EndpointName Admin
$navAppVeyor = New-PodeWebNavLink -Name 'Appveyor' -Icon 'factory' -Url 'https://ci.appveyor.com' -NewTab
$navDiv = New-PodeWebNavDivider
Set-PodeWebNavDefault -Items $navAppVeyor, $navDiv
Set-PodeWebHomePage -Layouts @(
New-PodeWebHero -Title 'Welcome!' -Message 'This is the home page' -Content @(
New-PodeWebText -Value 'Here is some text!' -InParagraph -Alignment Center
)
)
Add-PodeWebPage -Name Services -Icon Settings -ScriptBlock {
$value = $WebEvent.Query['value']
# table of services
if ([string]::IsNullOrWhiteSpace($value)) {
New-PodeWebCard -Content @(
New-PodeWebTable -Name 'Services' -DataColumn Name -Click -ScriptBlock {
foreach ($svc in (Get-Service)) {
[ordered]@{
Name = $svc.Name
Status = "$($svc.Status)"
}
}
}
)
}
# code-block with service info
else {
$svc = Get-Service -Name $value | Out-String
New-PodeWebCard -Name "$($value) Details" -Content @(
New-PodeWebCodeBlock -Value $svc -NoHighlight
)
}
}
}
The Services web page is just for testing purposes and was copied from the Pode.Web documentation, here.
I then issue the following POST to the /api/jobs/checkOut:
$Body = @{
JobID = "1.10.5555.8900";
JobURL = "INTERNAL"
} | ConvertTo-Json
Invoke-RestMethod -Uri https://172.30.231.75:8443/api/jobs/checkOut -Method Post -Body $Body -SkipCertificateCheck -Headers @{"Content-Type" = "application/json"}
This is then displayed on the Pode server console:
No dupe found.
Locked.
Setting job to Group 'Group1'.
Setting appliances within tracking object
Job 'INTERNAL'.
Return result.
Saving StateConfig.
WARNING: Resulting JSON is truncated as serialization has exceeded the set depth of 10.
[Warning]: [ContextId: b6942c87-8438-6bed-05af-7d36932aa8ae] Request timeout reached: 30 seconds
[Warning]: [ContextId: 3cf913ee-b41d-f21a-c4bd-08907aad20ba] Request timeout reached: 30 seconds
[Verbose]: [ContextId: 3cf913ee-b41d-f21a-c4bd-08907aad20ba] Disposing Context
[Verbose]: [ContextId: 3cf913ee-b41d-f21a-c4bd-08907aad20ba] Sending response timed-out
[Verbose]: [ContextId: 3cf913ee-b41d-f21a-c4bd-08907aad20ba] Response timed-out sent
[Verbose]: [ContextId: 3cf913ee-b41d-f21a-c4bd-08907aad20ba] Request disposed
[Verbose]: [ContextId: 3cf913ee-b41d-f21a-c4bd-08907aad20ba] Response disposed
[Verbose] OperationCanceledException: The operation was canceled.
at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Pode.PodeRequest.Receive(CancellationToken cancellationToken) in C:\Projects\pode-builds\2.11.1\src\Listener\PodeRequest.cs:line 243
[Verbose]: [ContextId: b6942c87-8438-6bed-05af-7d36932aa8ae] Disposing Context
[Verbose]: [ContextId: b6942c87-8438-6bed-05af-7d36932aa8ae] Sending response timed-out
[Verbose]: [ContextId: b6942c87-8438-6bed-05af-7d36932aa8ae] Response timed-out sent
[Verbose]: [ContextId: b6942c87-8438-6bed-05af-7d36932aa8ae] Request disposed
[Verbose]: [ContextId: b6942c87-8438-6bed-05af-7d36932aa8ae] Response disposed
[Verbose] OperationCanceledException: The operation was canceled.
at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Pode.PodeRequest.Receive(CancellationToken cancellationToken) in C:\Projects\pode-builds\2.11.1\src\Listener\PodeRequest.cs:line 243
[Verbose]: [ContextId: 3cf913ee-b41d-f21a-c4bd-08907aad20ba] Received request
[Warning]: [ContextId: fd0eb77f-3d0b-019a-cf45-63d9e03d5611] Request timeout reached: 30 seconds
[Verbose]: [ContextId: fd0eb77f-3d0b-019a-cf45-63d9e03d5611] Disposing Context
[Verbose]: [ContextId: fd0eb77f-3d0b-019a-cf45-63d9e03d5611] Sending response timed-out
[Verbose]: [ContextId: fd0eb77f-3d0b-019a-cf45-63d9e03d5611] Response timed-out sent
[Verbose]: [ContextId: b6942c87-8438-6bed-05af-7d36932aa8ae] Disposing Context
[Verbose] OperationCanceledException: The operation was canceled.
at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Pode.PodeRequest.Receive(CancellationToken cancellationToken) in C:\Projects\pode-builds\2.11.1\src\Listener\PodeRequest.cs:line 243
[Verbose]: [ContextId: fd0eb77f-3d0b-019a-cf45-63d9e03d5611] Request disposed
[Verbose]: [ContextId: fd0eb77f-3d0b-019a-cf45-63d9e03d5611] Response disposed
[Verbose]: [ContextId: fd0eb77f-3d0b-019a-cf45-63d9e03d5611] Received request
[Warning]: [ContextId: 77d9402e-20a6-6faa-d5c2-bb1834da37ec] Request timeout reached: 30 seconds
[Verbose]: [ContextId: 77d9402e-20a6-6faa-d5c2-bb1834da37ec] Disposing Context
[Verbose]: [ContextId: 77d9402e-20a6-6faa-d5c2-bb1834da37ec] Sending response timed-out
[Verbose] OperationCanceledException: The operation was canceled.
[Verbose]: [ContextId: 77d9402e-20a6-6faa-d5c2-bb1834da37ec] Response timed-out sent
at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Pode.PodeRequest.Receive(CancellationToken cancellationToken) in C:\Projects\pode-builds\2.11.1\src\Listener\PodeRequest.cs:line 243
[Verbose]: [ContextId: 77d9402e-20a6-6faa-d5c2-bb1834da37ec] Request disposed
[Verbose]: [ContextId: 77d9402e-20a6-6faa-d5c2-bb1834da37ec] Response disposed
[Verbose]: [ContextId: 77d9402e-20a6-6faa-d5c2-bb1834da37ec] Received request
[Warning]: [ContextId: b926254a-baa6-aa28-b9e6-036f86c84fff] Request timeout reached: 30 seconds
[Verbose]: [ContextId: b926254a-baa6-aa28-b9e6-036f86c84fff] Disposing Context
[Verbose] OperationCanceledException: The operation was canceled.
at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Pode.PodeRequest.Receive(CancellationToken cancellationToken) in C:\Projects\pode-builds\2.11.1\src\Listener\PodeRequest.cs:line 243
[Verbose]: [ContextId: b926254a-baa6-aa28-b9e6-036f86c84fff] Sending response timed-out
[Verbose]: [ContextId: b926254a-baa6-aa28-b9e6-036f86c84fff] Response timed-out sent
[Verbose]: [ContextId: b926254a-baa6-aa28-b9e6-036f86c84fff] Request disposed
[Verbose]: [ContextId: b926254a-baa6-aa28-b9e6-036f86c84fff] Response disposed
[Verbose]: [ContextId: b926254a-baa6-aa28-b9e6-036f86c84fff] Disposing Context
[Warning]: [ContextId: 03dde4ef-87e0-46ff-af6a-cb4e94f23a11] Request timeout reached: 30 seconds
[Verbose]: [ContextId: 03dde4ef-87e0-46ff-af6a-cb4e94f23a11] Disposing Context
[Verbose] OperationCanceledException: The operation was canceled.
at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Pode.PodeRequest.Receive(CancellationToken cancellationToken) in C:\Projects\pode-builds\2.11.1\src\Listener\PodeRequest.cs:line 243
[Verbose]: [ContextId: 03dde4ef-87e0-46ff-af6a-cb4e94f23a11] Sending response timed-out
[Verbose]: [ContextId: 03dde4ef-87e0-46ff-af6a-cb4e94f23a11] Response timed-out sent
[Verbose]: [ContextId: 03dde4ef-87e0-46ff-af6a-cb4e94f23a11] Request disposed
[Verbose]: [ContextId: 03dde4ef-87e0-46ff-af6a-cb4e94f23a11] Response disposed
[Verbose]: [ContextId: 03dde4ef-87e0-46ff-af6a-cb4e94f23a11] Disposing Context
[Warning]: [ContextId: 8d79a583-6779-108e-09b1-634d34370609] Request timeout reached: 30 seconds
[Verbose]: [ContextId: 8d79a583-6779-108e-09b1-634d34370609] Disposing Context
[Verbose]: [ContextId: 8d79a583-6779-108e-09b1-634d34370609] Sending response timed-out
[Verbose]: [ContextId: 8d79a583-6779-108e-09b1-634d34370609] Response timed-out sent
[Verbose]: [ContextId: 8d79a583-6779-108e-09b1-634d34370609] Request disposed
[Verbose]: [ContextId: 8d79a583-6779-108e-09b1-634d34370609] Response disposed
Prefacing the Save-PodeState call in the Add-PodeRoute with $null = or even piping to Out-Null, the error continues. Removing the Add-PodeWebPage code I don't get the error at all.
Here is state.json:
{
"CurrentJobs": {
"Scope": [],
"Value": [
{
"Name": "Group1",
"Appliances": [
null,
null,
null,
null
],
"JobID": "",
"JobUrl": "",
"State": "Stopped",
"Start": "0001-01-01T00:00:00",
"End": "0001-01-01T00:00:00"
},
{
"Name": "Group2",
"Appliances": [
null,
null,
null,
null
],
"JobID": "",
"JobUrl": "",
"State": "Stopped",
"Start": "0001-01-01T00:00:00",
"End": "0001-01-01T00:00:00"
},
{
"Name": "Group3",
"Appliances": [
null,
null,
null,
null
],
"JobID": "",
"JobUrl": "",
"State": "Stopped",
"Start": "0001-01-01T00:00:00",
"End": "0001-01-01T00:00:00"
},
{
"Name": "Group4",
"Appliances": [
null,
null,
null,
null
],
"JobID": "",
"JobUrl": "",
"State": "Stopped",
"Start": "0001-01-01T00:00:00",
"End": "0001-01-01T00:00:00"
},
{
"Name": "TotGroup",
"Appliances": [
null,
null,
null,
null
],
"JobID": "",
"JobUrl": "",
"State": "Stopped",
"Start": "0001-01-01T00:00:00",
"End": "0001-01-01T00:00:00"
},
{
"Name": "LTSGroup",
"Appliances": [
null,
null,
null,
null
],
"JobID": "",
"JobUrl": "",
"State": "Stopped",
"Start": "0001-01-01T00:00:00",
"End": "0001-01-01T00:00:00"
}
]
},
"CurrentConfig": {
"Value": {
"Groups": {
"Group1": [
"name1",
"name2",
"name3",
"namefex"
],
"Group2": [
"name5",
"name6",
"name7",
"namefex2"
],
"Group3": [
"name9",
"name10",
"name11",
"namefex3"
],
"Group4": [
"name13",
"name14",
"name15",
"namefex4"
],
"LTS": [
"namelts1",
"namelts2",
"namelts3",
"nameltsfex"
],
"TOT": [
"name-tot1",
"name-tot2",
"name-tot3",
"totfex"
]
},
"version": {
"ExpectedAPIVersion": 1234,
"Appliance1": "name1",
"Appliance2": "name2",
"Appliance3": "name3",
"Appliance4": "name4",
"key_1": "[REDACTED]",
"key_2": "[REDACTED]",
"key_3": "[REDACTED]"
},
"Config": {
"RemoteBackupPublicKey": "ssh-rsa [REDACTED]",
"Key1": "[REDACTED]",
"Key2": "[REDACTED]",
"Key3": "[REDACTED]",
"Key4": "[REDACTED]"
}
},
"Scope": []
},
"pode.web.app-path": {
"Value": "",
"Scope": [
"pode.web"
]
},
"pode.web.title": {
"Value": "Example",
"Scope": [
"pode.web"
]
},
"pode.web.logo": {
"Value": "",
"Scope": [
"pode.web"
]
},
"pode.web.favicon": {
"Value": "/pode.web/images/favicon.ico",
"Scope": [
"pode.web"
]
},
"pode.web.no-page-filter": {
"Value": false,
"Scope": [
"pode.web"
]
},
"pode.web.hide-sidebar": {
"Value": false,
"Scope": [
"pode.web"
]
},
"pode.web.social": {
"Value": {},
"Scope": [
"pode.web"
]
},
"pode.web.pages": {
"Value": {
"/": {
"Path": "/",
"Title": "Home",
"Layouts": [
{
"Title": "Welcome!",
"CssClasses": "",
"CssStyles": "",
"ID": "hero_tgehx",
"ComponentType": "Layout",
"Message": "This is the home page",
"Content": [
{
"ID": "txt_fmrxl",
"Parent": null,
"NoEvents": true,
"InParagraph": true,
"Value": "Here is some text!",
"CssClasses": "",
"CssStyles": "",
"Style": "Normal",
"ObjectType": "Text",
"Pronunciation": "",
"ComponentType": "Element",
"Alignment": "center"
}
],
"ObjectType": "Hero"
}
],
"IsSystem": true,
"Navigation": null,
"ObjectType": "Page",
"DisplayName": "Home",
"ComponentType": "Page",
"NoTitle": false,
"Name": "Home"
}
},
"Scope": [
"pode.web"
]
},
"pode.web.default-nav": {
"Value": [
{
"ID": "navlink_appveyor",
"Disabled": false,
"InDropdown": false,
"IsDynamic": false,
"NavType": "Link",
"Icon": "factory",
"DisplayName": "Appveyor",
"ComponentType": "Navigation",
"Url": "https://ci.appveyor.com",
"NewTab": true,
"Name": "Appveyor"
},
{
"InDropdown": false,
"ComponentType": "Navigation",
"NavType": "Divider"
}
],
"Scope": [
"pode.web"
]
},
"pode.web.endpoint-name": {
"Value": null,
"Scope": [
"pode.web"
]
},
"pode.web.custom-css": {
"Value": [],
"Scope": [
"pode.web"
]
},
"pode.web.custom-js": {
"Value": [],
"Scope": [
"pode.web"
]
},
"pode.web.theme": {
"Value": "dark",
"Scope": [
"pode.web"
]
},
"pode.web.custom-themes": {
"Value": {
"Themes": {},
"Default": null
},
"Scope": [
"pode.web"
]
}
}
Expected Behavior
I'm trying to implement an API service, and a web UI front end to show the data from the $state:CurrentJobs variable, and need to save its state across restarts.
Platform
- OS:
Windows Server 2016 (10.0.14393.7428) - Versions:
- Pode:
2.11.1 - Pode.Web:
0.8.3 - PowerShell:
7.4.5
- Pode: