Private/CancellationToken.ps1


<#
.SYNOPSIS
    Resets the cancellation token for a specific type in Pode.
.DESCRIPTION
    The `Reset-PodeCancellationToken` function disposes of the existing cancellation token
    for the specified type and reinitializes it with a new token. This ensures proper cleanup
    of disposable resources associated with the cancellation token.
.PARAMETER Type
    The type of cancellation token to reset. This is a mandatory parameter and must be
    provided as a string.
 
.EXAMPLE
    # Reset the cancellation token for the 'Cancellation' type
    Reset-PodeCancellationToken -Type Cancellation
 
.EXAMPLE
    # Reset the cancellation token for the 'Restart' type
    Reset-PodeCancellationToken -Type Restart
 
.EXAMPLE
    # Reset the cancellation token for the 'Suspend' type
    Reset-PodeCancellationToken -Type Suspend
 
.NOTES
    This function is used to manage cancellation tokens in Pode's internal context.
#>

function Reset-PodeCancellationToken {
    param(
        [Parameter(Mandatory = $true)]
        [validateset( 'Cancellation' , 'Restart', 'Suspend', 'Resume', 'Terminate', 'Start', 'Disable' )]
        [string[]]
        $Type
    )
    foreach ($item in $type) {
        # Ensure cleanup of disposable tokens
        Close-PodeDisposable -Disposable $PodeContext.Tokens[$item]

        # Reinitialize the Token
        $PodeContext.Tokens[$item] = [System.Threading.CancellationTokenSource]::new()
    }
}

<#
.SYNOPSIS
    Closes and disposes of specified cancellation tokens in the Pode context.
 
.DESCRIPTION
    The `Close-PodeCancellationToken` function ensures proper cleanup of disposable cancellation tokens
    within the `$PodeContext`. It allows you to specify one or more token types to close and dispose of,
    or you can dispose of all tokens if no type is specified.
 
    Supported token types include:
    - `Cancellation`
    - `Restart`
    - `Suspend`
    - `Resume`
    - `Terminate`
    - `Start`
    - `Disable`
 
    This function is essential for managing resources during the lifecycle of a Pode application,
    especially when cleaning up during shutdown or restarting.
 
.PARAMETER Type
    Specifies the type(s) of cancellation tokens to close. Valid values are:
    `Cancellation`, `Restart`, `Suspend`, `Resume`, `Terminate`, `Start`,'Disable'.
 
    If this parameter is not specified, all tokens in `$PodeContext.Tokens` will be disposed of.
 
.EXAMPLE
    Close-PodeCancellationToken -Type 'Suspend'
    Closes and disposes of the `Suspend` cancellation token in the Pode context.
 
.EXAMPLE
    Close-PodeCancellationToken -Type 'Restart', 'Terminate'
    Closes and disposes of the `Restart` and `Terminate` cancellation tokens in the Pode context.
 
.EXAMPLE
    Close-PodeCancellationToken
    Closes and disposes of all tokens in the Pode context.
 
.NOTES
    This is an internal function and may change in future releases of Pode.
 
#>



function Close-PodeCancellationToken {
    [CmdletBinding()]
    param(
        [Parameter()]
        [ValidateSet('Cancellation', 'Restart', 'Suspend', 'Resume', 'Terminate', 'Start', 'Disable' )]
        [string[]]
        $Type
    )
    if ($null -eq $Type) {
        $PodeContext.Tokens.Values | Close-PodeDisposable
    }
    else {
        foreach ($tokenType in $Type) {
            # Ensure cleanup of disposable tokens
            Close-PodeDisposable -Disposable $PodeContext.Tokens[$tokenType]
        }
    }
}




<#
.SYNOPSIS
    Waits for Pode suspension cancellation token to be reset.
 
.DESCRIPTION
    The `Test-PodeSuspensionToken` function checks the status of the suspension cancellation token within the `$PodeContext`.
    It enters a loop to wait for the `Suspend` cancellation token to be reset before proceeding.
    Each loop iteration includes a 1-second delay to minimize resource usage.
    The function returns a boolean indicating whether the suspension token was initially requested.
 
.EXAMPLE
    Test-PodeSuspensionToken
    Waits for the suspension token to be reset in the Pode context.
 
.OUTPUTS
    [bool]
    Indicates whether the suspension token was initially requested.
 
.NOTES
    This is an internal function and may change in future releases of Pode.
#>

function Test-PodeSuspensionToken {
    # Check if the Suspend token was initially requested
    $suspended = $PodeContext.Tokens.Suspend.IsCancellationRequested

    # Wait for the Suspend token to be reset
    while ($PodeContext.Tokens.Suspend.IsCancellationRequested) {
        Start-Sleep -Seconds 1
    }

    # Return whether the suspension token was initially requested
    return $suspended
}

<#
.SYNOPSIS
    Creates a set of cancellation tokens for managing Pode application states.
 
.DESCRIPTION
    The `Initialize-PodeCancellationToken` function initializes and returns a hashtable containing
    multiple cancellation tokens used for managing various states in a Pode application.
    These tokens provide coordinated control over application operations, such as cancellation,
    restart, suspension, resumption, termination, and start operations.
 
    The returned hashtable includes the following keys:
    - `Cancellation`: A token specifically for managing endpoint cancellation tasks.
    - `Restart`: A token for managing application restarts.
    - `Suspend`: A token for handling suspension operations.
    - `Resume`: A token for resuming operations after suspension.
    - `Terminate`: A token for managing application termination.
    - `Start`: A token for monitoring application startup.
    - `Disable`: A token for denying web access.
 
.EXAMPLE
    $tokens = Initialize-PodeCancellationToken
    Initializes a set of cancellation tokens and stores them in the `$tokens` variable.
 
.OUTPUTS
    [hashtable]
    A hashtable containing initialized cancellation tokens.
 
.NOTES
    This is an internal function and may change in future releases of Pode.
#>

function Initialize-PodeCancellationToken {
    # Initialize and return a hashtable containing various cancellation tokens.
    return @{
        # A cancellation token specifically for managing endpoint cancellation tasks.
        Cancellation = [System.Threading.CancellationTokenSource]::new()

        # A cancellation token specifically for managing application restart operations.
        Restart      = [System.Threading.CancellationTokenSource]::new()

        # A cancellation token for suspending operations in the Pode application.
        Suspend      = [System.Threading.CancellationTokenSource]::new()

        # A cancellation token for resuming operations after a suspension.
        Resume       = [System.Threading.CancellationTokenSource]::new()

        # A cancellation token for managing application termination.
        Terminate    = [System.Threading.CancellationTokenSource]::new()

        # A cancellation token for monitoring application startup.
        Start        = [System.Threading.CancellationTokenSource]::new()

        # A cancellation token for denying any web request.
        Disable      = [System.Threading.CancellationTokenSource]::new()
    }
}



<#
.SYNOPSIS
    Sets the Resume token for the Pode server to resume its operation from a suspended state.
 
.DESCRIPTION
    The Set-PodeResumeToken function ensures that the Resume token's cancellation is requested to signal that the server should
    resume its operation. Additionally, it resets other related tokens, such as Cancellation and Suspend, if they are in a requested state.
    This function prevents conflicts between tokens and ensures proper state management in the Pode server.
 
.NOTES
    This is an internal function and may change in future releases of Pode.
 
.EXAMPLE
    Set-PodeResumeToken
 
    Signals the Pode server to resume operations and resets relevant tokens.
#>

function Set-PodeResumeToken {

    # Ensure the Resume token is in a cancellation requested state
    Close-PodeCancellationTokenRequest -Type Resume

    # If the Cancellation token is in a requested state, reset it (unexpected scenario)
    if ($PodeContext.Tokens.Cancellation.IsCancellationRequested) {
        Reset-PodeCancellationToken -Type Cancellation
    }

    # Reset the Suspend token if it is in a cancellation requested state
    if ($PodeContext.Tokens.Suspend.IsCancellationRequested) {
        Reset-PodeCancellationToken -Type Suspend
    }
}


<#
.SYNOPSIS
    Sets the Suspend token for the Pode server to transition into a suspended state.
 
.DESCRIPTION
    The Set-PodeSuspendToken function ensures that the Suspend token's cancellation is requested to signal that the server should
    transition into a suspended state. Additionally, it sets the Cancellation token to prevent further operations while the server
    is suspended.
 
.NOTES
    This is an internal function and may change in future releases of Pode.
 
.EXAMPLE
    Set-PodeSuspendToken
 
    Signals the Pode server to transition into a suspended state by setting the Suspend token and the Cancellation token.
#>

function Set-PodeSuspendToken {
    # Ensure the Suspend and Cancellation tokens is in a cancellation requested state
    Close-PodeCancellationTokenRequest -Type Suspend, Cancellation
}


<#
.SYNOPSIS
    Sets the cancellation token(s) for the specified Pode server actions.
 
.DESCRIPTION
    The `Close-PodeCancellationTokenRequest` function cancels one or more specified tokens within the Pode server.
    These tokens are used to manage the server's lifecycle actions, such as Restart, Suspend, Resume, or Terminate.
    The function takes a mandatory parameter `$Type`, which determines the token(s) to be canceled.
    Supported types include: `Cancellation`, `Restart`, `Suspend`, `Resume`, `Terminate`, `Start`, and `Disable`.
 
.PARAMETER Type
    Specifies the token(s) to be canceled. This parameter accepts one or more values from a predefined set.
    Allowed values: `Cancellation`, `Restart`, `Suspend`, `Resume`, `Terminate`, `Start`, `Disable`.
 
.EXAMPLE
    Close-PodeCancellationTokenRequest -Type 'Restart'
 
    Cancels the Restart token for the Pode server.
 
.EXAMPLE
    Close-PodeCancellationTokenRequest -Type 'Suspend','Terminate'
 
    Cancels both the Suspend and Terminate tokens for the Pode server.
 
.NOTES
    This function is an internal utility and may change in future releases of Pode.
#>

function Close-PodeCancellationTokenRequest {
    param(
        [Parameter(Mandatory = $true)]
        [ValidateSet('Cancellation', 'Restart', 'Suspend', 'Resume', 'Terminate', 'Start', 'Disable')]
        [string[]]
        $Type
    )

    # Iterate over each provided type and cancel its corresponding token if not already canceled
    foreach ($item in $Type) {
        if ($PodeContext.Tokens.ContainsKey($item)) {
            if (! $PodeContext.Tokens[$item].IsCancellationRequested) {
                # Cancel the specified token
                $PodeContext.Tokens[$item].Cancel()
            }
        }
    }
}

<#
.SYNOPSIS
    Waits for a specific Pode server cancellation token to be reset.
 
.DESCRIPTION
    The `Wait-PodeCancellationTokenRequest` function continuously checks the status of a specified cancellation token
    in the Pode server context. It pauses execution in a loop until the token's cancellation request is cleared.
 
.PARAMETER Type
    Specifies the token to wait for. This parameter accepts one value from a predefined set.
    Allowed values: `Cancellation`, `Restart`, `Suspend`, `Resume`, `Terminate`, `Start`, `Disable`.
 
.EXAMPLE
    Wait-PodeCancellationTokenRequest -Type 'Restart'
 
    Waits until the Restart token is reset and no longer has a cancellation request.
 
.EXAMPLE
    Wait-PodeCancellationTokenRequest -Type 'Suspend'
 
    Waits for the Suspend token to be reset, pausing execution until the token is no longer in a cancellation state.
 
.NOTES
    - This function is part of Pode's internal utilities and may change in future releases.
    - It uses a simple loop with a 1-second sleep interval to reduce CPU usage while waiting.
 
#>

function Wait-PodeCancellationTokenRequest {
    param(
        [Parameter(Mandatory = $true)]
        [ValidateSet('Cancellation', 'Restart', 'Suspend', 'Resume', 'Terminate', 'Start', 'Disable')]
        [string]
        $Type
    )

    # Wait for the token to be reset, with exponential back-off
    $count = 1
    while (! $PodeContext.Tokens[$Type].IsCancellationRequested) {
        Start-Sleep -Milliseconds (100 * $count)
        $count = [System.Math]::Min($count + 1, 20)
    }
}

<#
.SYNOPSIS
    Evaluates whether a specified Pode server token has an active cancellation request.
 
.DESCRIPTION
    The `Test-PodeCancellationTokenRequest` function checks the cancellation state of a given token
    in the Pode server context. It determines whether the token has been marked for cancellation
    and optionally waits for the cancellation to occur if the `-Wait` parameter is specified.
 
.PARAMETER Type
    Specifies the token to check for an active cancellation request.
    Acceptable values include predefined token types in Pode:
    - `Cancellation`
    - `Restart`
    - `Suspend`
    - `Resume`
    - `Terminate`
    - `Start`
    - `Disable`
 
.OUTPUTS
    [bool] Returns `$true` if the specified token has an active cancellation request, otherwise `$false`.
 
.EXAMPLE
    Test-PodeCancellationTokenRequest -Type 'Restart'
 
    Checks if the Restart token has an active cancellation request and returns `$true` or `$false`.
 
.NOTES
    This function is an internal utility for Pode and may be subject to change in future releases.
#>

function Test-PodeCancellationTokenRequest {
    param(
        [Parameter(Mandatory = $true)]
        [ValidateSet('Cancellation', 'Restart', 'Suspend', 'Resume', 'Terminate', 'Start', 'Disable')]
        [string]
        $Type
    )

    # Check if the specified token has an active cancellation request
    $cancelled = $PodeContext.Tokens[$Type].IsCancellationRequested

    return $cancelled
}


<#
.SYNOPSIS
    Resolves cancellation token requests and executes corresponding server actions.
 
.DESCRIPTION
    This internal function evaluates cancellation token requests to handle actions
    such as restarting the server, enabling/disabling the server, or suspending/resuming
    its operations. It interacts with the Pode server's context and state to perform
    the necessary operations based on the allowed actions and current state.
 
.NOTES
    This is an internal function and may change in future releases of Pode.
 
.EXAMPLE
    Resolve-PodeCancellationToken
    Evaluates any pending cancellation token requests and applies the appropriate server actions.
#>


function Resolve-PodeCancellationToken {

    #Retrieve the current state of the Pode server
    $serverState = Get-PodeServerState

    if ($PodeContext.Server.AllowedActions.Restart -and (Test-PodeCancellationTokenRequest -Type Restart)) {
        Restart-PodeInternalServer
        return
    }

    # Handle enable/disable server actions
    if ($PodeContext.Server.AllowedActions.Disable -and ($ServerState -eq [Pode.PodeServerState]::Running)) {
        if (Test-PodeServerIsEnabled) {
            if (Test-PodeCancellationTokenRequest -Type Disable) {
                Disable-PodeServerInternal
                Show-PodeConsoleInfo -ShowTopSeparator
                return
            }
        }
        else {
            if (! (Test-PodeCancellationTokenRequest -Type Disable)) {
                Enable-PodeServerInternal
                Show-PodeConsoleInfo -ShowTopSeparator
                return
            }
        }
    }
    # Handle suspend/resume actions
    if ($PodeContext.Server.AllowedActions.Suspend) {
        if ((Test-PodeCancellationTokenRequest -Type Resume) -and ($ServerState -eq [Pode.PodeServerState]::Resuming)) {
            Resume-PodeServerInternal -Timeout $PodeContext.Server.AllowedActions.Timeout.Resume
            return
        }
        elseif ((Test-PodeCancellationTokenRequest -Type Suspend) -and ($ServerState -eq [Pode.PodeServerState]::Suspending)) {
            Suspend-PodeServerInternal -Timeout $PodeContext.Server.AllowedActions.Timeout.Suspend
            return
        }
    }
}