Is there a simple, UD-native way for an API call to trigger an asynchronous process?
Something like
$Endpoint = New-UDEndpoint -Url “/Request” -Method Post -Endpoint {
Param( $Body )
$Parameters = $Body | ConvertFrom-Json
$ValidInput = Validate-InputPameters
If ( $ValidInput )
{
Return 200 # Request posted successfully
#
# Complete lengthy request process here AFTER returning HTTP response
#
}
Else
{
Return 400 # No. Try again.
}
}
I believe I had tested some endpoint with Start-Job with success some time ago.
You could give that a try.
However, if using IIS, the application pool could technically recycle on you if the job is running for too long. To avoid that, or if start-job does not do the trick and you are working from a Windows environment, you can launch your job as an independant process using :
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList 'MyExternalProcess.exe'
I’m doing something like this myself. I have a lengthy user provisioning procedure which would take about two minutes to run. This obviously would not be acceptable for a REST request.
My approach is to call my Create-User function from the UD endpoint. The Create-User function is a master script which dot sources then calls a number of standalone functions.
These functions operate in separate runspaces after the initial Create-User has terminated. The response takes about 4 seconds but the jobs run in the background for about two minutes and log their output to a unified log file.
Function Create-User{
$kFunctions = 'C:\onboard-term-api\Functions'
. "$kFunctions\CreateHomeDir.ps1"
. "$kFunctions\CreateMailbox.ps1"
. "$kFunctions\CreateSlackAcc.ps1"
Invoke-CreateHomeDir -Username $username -DomainController $DomainController -FunctionsDir $kFunctions
# Invoke-CreateMailbox
# Invoke-CreateSlackAcc
# Invoke-LotsMoreStuff
Return $UserCreationDetails | ConvertTo-Json
}
An example of an async script to create a home directory in a separate runspace.
It can be hard to troubleshoot a failing script running in a separate workspace so that’s why I added the DebugMode switch. However, if this is set then the calling script will wait on the runspace to complete so only call this when you need it.
Function Invoke-HomeDirectory{
[CmdletBinding()]
param(
[String]
$Fileserver,
[String]
$Username,
[String]
$DomainController,
[Switch]
$DebugMode
)
# Params that will be used in the runspace to call New-Homedirectory
$ParamListHome = @{
Username = $username
Region = $fileserver
DomainController = $DomainController
Functions = $FunctionsDir
}
$scriptblockHome = {
Param (
[String] $Username,
[String] $Region,
[String] $DomainController,
[String] $Functions
)
Import-Module "$Functions\Modules\homeDirectory" -Verbose
Try {
Logwrite -Username $Username -Logstring "Running: New-HomeDirectory command from Invoke-HomeDirectory initiated runspace"
New-HomeDirectory -Username $Username -Region $region -DomainController $DomainController -Verbose
}
Catch {
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
return "$FailedItem - the error message was $ErrorMessage"
Break
}
}
$runspaceHome = [Powershell]::Create()
$null = $runspaceHome.AddScript($scriptblockHome)
$null = $runspaceHome.AddParameters($ParamListHome)
#$runspaceHome.Runspace
#$runspaceHome.commands.commands
#$runspaceHome.commands.commands.parameters
$asyncObjectHome = $runspaceHome.BeginInvoke() # Fires off in background
If($DebugMode){
# Check status of background job
$dataHome = $runspaceHome.EndInvoke($asyncObjectHome)
LogWrite -Username $username -Logstring $dataHome
}
}
Hope this is what you are after.
Michael
Michael,
Thank you for your response and examples. But I am somewhat familiar with runspaces. (See the chapter on runspaces written by me in the PowerShell Conference Book, Vol 1.)
I was hoping UD had a simple built-in solution. But it is helpful to understand that runspaces created in an endpoint can outlive the endpoint. Though it could get messy if they sometimes hang. I supposed in that case I would have to double up, and have a management runspace that creates and cleans up after the worker runspaces, handling time outs, etc.
Thanks,
Tim Curwick
1 Like
That’s hilarious.
Maybe at some stage someone might find the example useful anyway.
But you make a good point it would be better if this didn’t require so much heavy lifting.
You got me interested in that book now too