diff --git a/d365fo.integrations/d365fo.integrations.psd1 b/d365fo.integrations/d365fo.integrations.psd1
index c387e35..834e0b6 100644
--- a/d365fo.integrations/d365fo.integrations.psd1
+++ b/d365fo.integrations/d365fo.integrations.psd1
@@ -3,7 +3,7 @@
RootModule = 'd365fo.integrations.psm1'
# Version number of this module.
- ModuleVersion = '0.4.35'
+ ModuleVersion = '0.4.38'
# ID used to uniquely identify this module
GUID = 'd2667b62-1436-42b3-a840-ab6b4a0e5aa0'
diff --git a/d365fo.integrations/d365fo.integrations.psm1 b/d365fo.integrations/d365fo.integrations.psm1
index 3df187c..c1d10bb 100644
--- a/d365fo.integrations/d365fo.integrations.psm1
+++ b/d365fo.integrations/d365fo.integrations.psm1
@@ -1,5 +1,5 @@
$script:ModuleRoot = $PSScriptRoot
-$script:ModuleVersion = '0.4.35'
+$script:ModuleVersion = '0.4.38'
$Script:TimeSignals = @{}
diff --git a/d365fo.integrations/functions/add-d365odataconfig.ps1 b/d365fo.integrations/functions/add-d365odataconfig.ps1
index 23e606d..669b6ef 100644
--- a/d365fo.integrations/functions/add-d365odataconfig.ps1
+++ b/d365fo.integrations/functions/add-d365odataconfig.ps1
@@ -55,24 +55,6 @@
Tags: Integrations, Integration, Bearer Token, Token, OData, Configuration
Author: Mötz Jensen (@Splaxi)
-
- .LINK
- Clear-D365ActiveBroadcastMessageConfig
-
- .LINK
- Get-D365ActiveBroadcastMessageConfig
-
- .LINK
- Get-D365BroadcastMessageConfig
-
- .LINK
- Remove-D365BroadcastMessageConfig
-
- .LINK
- Send-D365BroadcastMessage
-
- .LINK
- Set-D365ActiveBroadcastMessageConfig
#>
function Add-D365ODataConfig {
diff --git a/d365fo.integrations/functions/get-d365activeodataconfig.ps1 b/d365fo.integrations/functions/get-d365activeodataconfig.ps1
index 86f4e72..a1c7568 100644
--- a/d365fo.integrations/functions/get-d365activeodataconfig.ps1
+++ b/d365fo.integrations/functions/get-d365activeodataconfig.ps1
@@ -22,24 +22,6 @@
Tags: OData, Environment, Config, Configuration, ClientId, ClientSecret
Author: Mötz Jensen (@Splaxi)
-
- .LINK
- Add-D365BroadcastMessageConfig
-
- .LINK
- Clear-D365ActiveBroadcastMessageConfig
-
- .LINK
- Get-D365BroadcastMessageConfig
-
- .LINK
- Remove-D365BroadcastMessageConfig
-
- .LINK
- Send-D365BroadcastMessage
-
- .LINK
- Set-D365ActiveBroadcastMessageConfig
#>
function Get-D365ActiveODataConfig {
diff --git a/d365fo.integrations/functions/get-d365odataconfig.ps1 b/d365fo.integrations/functions/get-d365odataconfig.ps1
index aaf005b..eb000a1 100644
--- a/d365fo.integrations/functions/get-d365odataconfig.ps1
+++ b/d365fo.integrations/functions/get-d365odataconfig.ps1
@@ -40,24 +40,6 @@
Tags: OData, Environment, Config, Configuration, ClientId, ClientSecret
Author: Mötz Jensen (@Splaxi)
-
- .LINK
- Add-D365BroadcastMessageConfig
-
- .LINK
- Clear-D365ActiveBroadcastMessageConfig
-
- .LINK
- Get-D365ActiveBroadcastMessageConfig
-
- .LINK
- Remove-D365BroadcastMessageConfig
-
- .LINK
- Send-D365BroadcastMessage
-
- .LINK
- Set-D365ActiveBroadcastMessageConfig
#>
function Get-D365ODataConfig {
diff --git a/d365fo.integrations/functions/import-d365odataentity.ps1 b/d365fo.integrations/functions/import-d365odataentity.ps1
index 88ba887..2962465 100644
--- a/d365fo.integrations/functions/import-d365odataentity.ps1
+++ b/d365fo.integrations/functions/import-d365odataentity.ps1
@@ -246,7 +246,6 @@ function Import-D365ODataEntity {
Invoke-RequestHandler -Method POST -Uri $odataEndpoint.Uri.AbsoluteUri -Headers $headers -ContentType "application/json;charset=$PayloadCharset" -Payload $Payload -RetryTimeout $RetryTimeout
if (Test-PSFFunctionInterrupt) { return }
-
}
catch {
$messageString = "Something went wrong while importing data through the OData endpoint for the entity: $EntityName"
diff --git a/d365fo.integrations/functions/invoke-d365restendpoint.ps1 b/d365fo.integrations/functions/invoke-d365restendpoint.ps1
index 84f3e11..0a7c5dd 100644
--- a/d365fo.integrations/functions/invoke-d365restendpoint.ps1
+++ b/d365fo.integrations/functions/invoke-d365restendpoint.ps1
@@ -32,6 +32,30 @@
The charset has to be a valid http charset like: ASCII, ANSI, ISO-8859-1, UTF-8
+ .PARAMETER RetryTimeout
+ The retry timeout, before the cmdlet should quit retrying based on the 429 status code
+
+ Needs to be provided in the timspan notation:
+ "hh:mm:ss"
+
+ hh is the number of hours, numerical notation only
+ mm is the number of minutes
+ ss is the numbers of seconds
+
+ Each section of the timeout has to valid, e.g.
+ hh can maximum be 23
+ mm can maximum be 59
+ ss can maximum be 59
+
+ Not setting this parameter will result in the cmdlet to try for ever to handle the 429 push back from the endpoint
+
+ .PARAMETER ThrottleSeed
+ Instruct the cmdlet to invoke a thread sleep between 1 and ThrottleSeed value
+
+ This is to help to mitigate the 429 retry throttling on the OData / Custom Service endpoints
+
+ It makes most sense if you are running things a outer loop, where you will hit the OData / Custom Service endpoints with a burst of calls in a short time
+
.PARAMETER Tenant
Azure Active Directory (AAD) tenant id (Guid) that the D365FO environment is connected to, that you want to access through REST endpoint
@@ -89,6 +113,26 @@
The ServiceName used for the import is "UserSessionService/AifUserSessionService/GetUserSessionInfo".
The Payload is a valid json string, containing all the needed properties.
+ .EXAMPLE
+ PS C:\> $Payload = '{"RateTypeName": "TEST", "FromCurrency": "DKK", "ToCurrency": "EUR", "StartDate": "2019-01-03T00:00:00Z", "Rate": 745.10, "ConversionFactor": "Hundred", "RateTypeDescription": "TEST"}'
+ PS C:\> Invoke-D365RestEndpoint -ServiceName "UserSessionService/AifUserSessionService/GetUserSessionInfo" -Payload $Payload -RetryTimeout "00:01:00"
+
+ This will invoke the REST endpoint in the Dynamics 365 Finance & Operations environment, and try for 1 minute to handle 429.
+ First the desired json data is put into the $Payload variable.
+ The ServiceName used for the import is "UserSessionService/AifUserSessionService/GetUserSessionInfo".
+ The $Payload variable is passed to the cmdlet.
+ It will only try to handle 429 retries for 1 minute, before failing.
+
+ .EXAMPLE
+ PS C:\> $Payload = '{"RateTypeName": "TEST", "FromCurrency": "DKK", "ToCurrency": "EUR", "StartDate": "2019-01-03T00:00:00Z", "Rate": 745.10, "ConversionFactor": "Hundred", "RateTypeDescription": "TEST"}'
+ PS C:\> Invoke-D365RestEndpoint -ServiceName "UserSessionService/AifUserSessionService/GetUserSessionInfo" -Payload $Payload -ThrottleSeed 2
+
+ This will invoke the REST endpoint in the Dynamics 365 Finance & Operations environment, and sleep/pause between 1 and 2 seconds.
+ First the desired json data is put into the $Payload variable.
+ The ServiceName used for the import is "UserSessionService/AifUserSessionService/GetUserSessionInfo".
+ The $Payload variable is passed to the cmdlet.
+ It will use the ThrottleSeed 2 to sleep/pause the execution, to mitigate the 429 pushback from the endpoint.
+
.NOTES
Tags: REST, Endpoint, Custom Service, Services
@@ -107,6 +151,10 @@ function Invoke-D365RestEndpoint {
[string] $PayloadCharset = "UTF-8",
+ [Timespan] $RetryTimeout = "00:00:00",
+
+ [int] $ThrottleSeed,
+
[Alias('$AadGuid')]
[string] $Tenant = $Script:ODataTenant,
@@ -130,6 +178,28 @@ function Invoke-D365RestEndpoint {
)
begin {
+ if ([System.String]::IsNullOrEmpty($SystemUrl)) {
+ Write-PSFMessage -Level Verbose -Message "The SystemUrl parameter was empty, using the Url parameter as the OData endpoint base address." -Target $SystemUrl
+ $SystemUrl = $Url
+ }
+
+ if ([System.String]::IsNullOrEmpty($Url) -or [System.String]::IsNullOrEmpty($SystemUrl)) {
+ $messageString = "It seems that you didn't supply a valid value for the Url parameter. You need specify the Url parameter or add a configuration with the Add-D365ODataConfig cmdlet."
+ Write-PSFMessage -Level Host -Message $messageString -Exception $PSItem.Exception -Target $entityName
+ Stop-PSFFunction -Message "Stopping because of errors." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) -ErrorRecord $_
+ return
+ }
+
+ if ($Url.Substring($Url.Length - 1) -eq "/") {
+ Write-PSFMessage -Level Verbose -Message "The Url parameter had a tailing slash, which shouldn't be there. Removing the tailling slash." -Target $Url
+ $Url = $Url.Substring(0, $Url.Length - 1)
+ }
+
+ if ($SystemUrl.Substring($SystemUrl.Length - 1) -eq "/") {
+ Write-PSFMessage -Level Verbose -Message "The SystemUrl parameter had a tailing slash, which shouldn't be there. Removing the tailling slash." -Target $Url
+ $SystemUrl = $SystemUrl.Substring(0, $SystemUrl.Length - 1)
+ }
+
if (-not $Token) {
$bearerParms = @{
Url = $Url
@@ -186,7 +256,9 @@ function Invoke-D365RestEndpoint {
try {
Write-PSFMessage -Level Verbose -Message "Executing http request against the REST endpoint." -Target $($restEndpoint.Uri.AbsoluteUri)
- Invoke-RestMethod @params
+ Invoke-RequestHandler -Method POST -Uri $restEndpoint.Uri.AbsoluteUri -Headers $headers -ContentType "application/json;charset=$PayloadCharset" -Payload $Payload -RetryTimeout $RetryTimeout
+
+ if (Test-PSFFunctionInterrupt) { return }
}
catch {
$messageString = "Something went wrong while importing data through the REST endpoint for the entity: $ServiceName"
@@ -195,6 +267,10 @@ function Invoke-D365RestEndpoint {
return
}
+ if ($ThrottleSeed) {
+ Start-Sleep -Seconds $(Get-Random -Minimum 1 -Maximum $ThrottleSeed)
+ }
+
Invoke-TimeSignal -End
}
}
\ No newline at end of file
diff --git a/d365fo.integrations/functions/remove-d365odataconfig.ps1 b/d365fo.integrations/functions/remove-d365odataconfig.ps1
new file mode 100644
index 0000000..df49dad
--- /dev/null
+++ b/d365fo.integrations/functions/remove-d365odataconfig.ps1
@@ -0,0 +1,62 @@
+
+<#
+ .SYNOPSIS
+ Remove an OData config
+
+ .DESCRIPTION
+ Removes an OData config from the configuration store
+
+ .PARAMETER Name
+ The name of the OData configuration you are about to remove from the configuration store
+
+ .PARAMETER Temporary
+ Instruct the cmdlet to only temporarily remove the OData configuration from the configuration store
+
+ .EXAMPLE
+ PS C:\> Remove-D365ODataConfig -Name "UAT"
+
+ This will create an new OData configuration with the name "UAT".
+
+ .NOTES
+ Tags: Integrations, Integration, Bearer Token, Token, OData, Configuration
+
+ Author: Mötz Jensen (@Splaxi)
+#>
+
+function Remove-D365ODataConfig {
+ [CmdletBinding()]
+ param (
+ [Parameter(Mandatory = $true)]
+ [string] $Name,
+
+ [switch] $Temporary
+ )
+
+ $Name = $Name.ToLower()
+
+ if ($Name -match '\*') {
+ Write-PSFMessage -Level Host -Message "The name cannot contain wildcard character."
+ Stop-PSFFunction -Message "Stopping because the name contains wildcard character."
+ return
+ }
+
+ if (-not ((Get-PSFConfig -FullName "d365fo.integrations.odata.*.name").Value -contains $Name)) {
+ Write-PSFMessage -Level Host -Message "An OData configuration with that name doesn't exists."
+ Stop-PSFFunction -Message "Stopping because an OData configuration with that name doesn't exists."
+ return
+ }
+
+ $res = (Get-PSFConfig -FullName "d365fo.integrations.active.odata.config.name").Value
+
+ if ($res -eq $Name) {
+ Write-PSFMessage -Level Host -Message "The active OData configuration is the same as the one you're trying to remove. Please set another configuration as active, before removing this one."
+ Stop-PSFFunction -Message "Stopping because the active OData configuration is the same as the one trying to be removed."
+ return
+ }
+
+ foreach ($config in Get-PSFConfig -FullName "d365fo.integrations.odata.$Name.*") {
+ Set-PSFConfig -FullName $config.FullName -Value ""
+
+ if (-not $Temporary) { Unregister-PSFConfig -FullName $config.FullName -Scope UserDefault }
+ }
+}
\ No newline at end of file
diff --git a/d365fo.integrations/tests/functions/Invoke-D365RestEndpoint.Tests.ps1 b/d365fo.integrations/tests/functions/Invoke-D365RestEndpoint.Tests.ps1
index 70f713f..55f2481 100644
--- a/d365fo.integrations/tests/functions/Invoke-D365RestEndpoint.Tests.ps1
+++ b/d365fo.integrations/tests/functions/Invoke-D365RestEndpoint.Tests.ps1
@@ -50,6 +50,32 @@
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
}
+ It 'Should have the expected parameter RetryTimeout' {
+ $parameter = (Get-Command Invoke-D365RestEndpoint).Parameters['RetryTimeout']
+ $parameter.Name | Should -Be 'RetryTimeout'
+ $parameter.ParameterType.ToString() | Should -Be System.TimeSpan
+ $parameter.IsDynamic | Should -Be $False
+ $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
+ $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
+ $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 3
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
+ }
+ It 'Should have the expected parameter ThrottleSeed' {
+ $parameter = (Get-Command Invoke-D365RestEndpoint).Parameters['ThrottleSeed']
+ $parameter.Name | Should -Be 'ThrottleSeed'
+ $parameter.ParameterType.ToString() | Should -Be System.Int32
+ $parameter.IsDynamic | Should -Be $False
+ $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
+ $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
+ $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 4
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
+ }
It 'Should have the expected parameter Tenant' {
$parameter = (Get-Command Invoke-D365RestEndpoint).Parameters['Tenant']
$parameter.Name | Should -Be 'Tenant'
@@ -58,7 +84,7 @@
$parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
$parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
$parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
- $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 3
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 5
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
@@ -71,7 +97,7 @@
$parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
$parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
$parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
- $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 4
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 6
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
@@ -84,7 +110,7 @@
$parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
$parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
$parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
- $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 5
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 7
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
@@ -97,7 +123,7 @@
$parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
$parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
$parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
- $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 6
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 8
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
@@ -110,7 +136,7 @@
$parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
$parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
$parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
- $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 7
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 9
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
@@ -123,7 +149,7 @@
$parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
$parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
$parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
- $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 8
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 10
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
@@ -149,7 +175,7 @@
$parameter.ParameterSets.Keys | Should -Be '__AllParameterSets'
$parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets'
$parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False
- $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 9
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 11
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
$parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
@@ -159,7 +185,7 @@
Describe "Testing parameterset __AllParameterSets" {
<#
__AllParameterSets -ServiceName
- __AllParameterSets -ServiceName -Payload -PayloadCharset -Tenant -Url -SystemUrl -ClientId -ClientSecret -Token -EnableException -TimeoutSec
+ __AllParameterSets -ServiceName -Payload -PayloadCharset -RetryTimeout -ThrottleSeed -Tenant -Url -SystemUrl -ClientId -ClientSecret -Token -EnableException -TimeoutSec
#>
}
diff --git a/docs/Add-D365ODataConfig.md b/docs/Add-D365ODataConfig.md
index 6debdd9..a118292 100644
--- a/docs/Add-D365ODataConfig.md
+++ b/docs/Add-D365ODataConfig.md
@@ -193,16 +193,3 @@ Tags: Integrations, Integration, Bearer Token, Token, OData, Configuration
Author: Mötz Jensen (@Splaxi)
## RELATED LINKS
-
-[Clear-D365ActiveBroadcastMessageConfig]()
-
-[Get-D365ActiveBroadcastMessageConfig]()
-
-[Get-D365BroadcastMessageConfig]()
-
-[Remove-D365BroadcastMessageConfig]()
-
-[Send-D365BroadcastMessage]()
-
-[Set-D365ActiveBroadcastMessageConfig]()
-
diff --git a/docs/Get-D365ActiveODataConfig.md b/docs/Get-D365ActiveODataConfig.md
index a02ed29..13fbdf3 100644
--- a/docs/Get-D365ActiveODataConfig.md
+++ b/docs/Get-D365ActiveODataConfig.md
@@ -74,16 +74,3 @@ Tags: OData, Environment, Config, Configuration, ClientId, ClientSecret
Author: Mötz Jensen (@Splaxi)
## RELATED LINKS
-
-[Add-D365BroadcastMessageConfig]()
-
-[Clear-D365ActiveBroadcastMessageConfig]()
-
-[Get-D365BroadcastMessageConfig]()
-
-[Remove-D365BroadcastMessageConfig]()
-
-[Send-D365BroadcastMessage]()
-
-[Set-D365ActiveBroadcastMessageConfig]()
-
diff --git a/docs/Get-D365ODataConfig.md b/docs/Get-D365ODataConfig.md
index ad0b340..3884347 100644
--- a/docs/Get-D365ODataConfig.md
+++ b/docs/Get-D365ODataConfig.md
@@ -111,16 +111,3 @@ Tags: OData, Environment, Config, Configuration, ClientId, ClientSecret
Author: Mötz Jensen (@Splaxi)
## RELATED LINKS
-
-[Add-D365BroadcastMessageConfig]()
-
-[Clear-D365ActiveBroadcastMessageConfig]()
-
-[Get-D365ActiveBroadcastMessageConfig]()
-
-[Remove-D365BroadcastMessageConfig]()
-
-[Send-D365BroadcastMessage]()
-
-[Set-D365ActiveBroadcastMessageConfig]()
-
diff --git a/docs/Invoke-D365RestEndpoint.md b/docs/Invoke-D365RestEndpoint.md
index fa70fce..cb4df33 100644
--- a/docs/Invoke-D365RestEndpoint.md
+++ b/docs/Invoke-D365RestEndpoint.md
@@ -14,8 +14,9 @@ Invoke a REST Endpoint in Dynamics 365 Finance & Operations
```
Invoke-D365RestEndpoint [-ServiceName] [[-Payload] ] [[-PayloadCharset] ]
- [[-Tenant] ] [[-Url] ] [[-SystemUrl] ] [[-ClientId] ]
- [[-ClientSecret] ] [[-Token] ] [-EnableException] [[-TimeoutSec] ] []
+ [[-RetryTimeout] ] [[-ThrottleSeed] ] [[-Tenant] ] [[-Url] ]
+ [[-SystemUrl] ] [[-ClientId] ] [[-ClientSecret] ] [[-Token] ]
+ [-EnableException] [[-TimeoutSec] ] []
```
## DESCRIPTION
@@ -58,6 +59,32 @@ It will get a fresh token, saved it into the token variable and pass it to the c
The ServiceName used for the import is "UserSessionService/AifUserSessionService/GetUserSessionInfo".
The Payload is a valid json string, containing all the needed properties.
+### EXAMPLE 4
+```
+$Payload = '{"RateTypeName": "TEST", "FromCurrency": "DKK", "ToCurrency": "EUR", "StartDate": "2019-01-03T00:00:00Z", "Rate": 745.10, "ConversionFactor": "Hundred", "RateTypeDescription": "TEST"}'
+```
+
+PS C:\\\> Invoke-D365RestEndpoint -ServiceName "UserSessionService/AifUserSessionService/GetUserSessionInfo" -Payload $Payload -RetryTimeout "00:01:00"
+
+This will invoke the REST endpoint in the Dynamics 365 Finance & Operations environment, and try for 1 minute to handle 429.
+First the desired json data is put into the $Payload variable.
+The ServiceName used for the import is "UserSessionService/AifUserSessionService/GetUserSessionInfo".
+The $Payload variable is passed to the cmdlet.
+It will only try to handle 429 retries for 1 minute, before failing.
+
+### EXAMPLE 5
+```
+$Payload = '{"RateTypeName": "TEST", "FromCurrency": "DKK", "ToCurrency": "EUR", "StartDate": "2019-01-03T00:00:00Z", "Rate": 745.10, "ConversionFactor": "Hundred", "RateTypeDescription": "TEST"}'
+```
+
+PS C:\\\> Invoke-D365RestEndpoint -ServiceName "UserSessionService/AifUserSessionService/GetUserSessionInfo" -Payload $Payload -ThrottleSeed 2
+
+This will invoke the REST endpoint in the Dynamics 365 Finance & Operations environment, and sleep/pause between 1 and 2 seconds.
+First the desired json data is put into the $Payload variable.
+The ServiceName used for the import is "UserSessionService/AifUserSessionService/GetUserSessionInfo".
+The $Payload variable is passed to the cmdlet.
+It will use the ThrottleSeed 2 to sleep/pause the execution, to mitigate the 429 pushback from the endpoint.
+
## PARAMETERS
### -ServiceName
@@ -121,6 +148,54 @@ Accept pipeline input: False
Accept wildcard characters: False
```
+### -RetryTimeout
+The retry timeout, before the cmdlet should quit retrying based on the 429 status code
+
+Needs to be provided in the timspan notation:
+"hh:mm:ss"
+
+hh is the number of hours, numerical notation only
+mm is the number of minutes
+ss is the numbers of seconds
+
+Each section of the timeout has to valid, e.g.
+hh can maximum be 23
+mm can maximum be 59
+ss can maximum be 59
+
+Not setting this parameter will result in the cmdlet to try for ever to handle the 429 push back from the endpoint
+
+```yaml
+Type: TimeSpan
+Parameter Sets: (All)
+Aliases:
+
+Required: False
+Position: 4
+Default value: 00:00:00
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -ThrottleSeed
+Instruct the cmdlet to invoke a thread sleep between 1 and ThrottleSeed value
+
+This is to help to mitigate the 429 retry throttling on the OData / Custom Service endpoints
+
+It makes most sense if you are running things a outer loop, where you will hit the OData / Custom Service endpoints with a burst of calls in a short time
+
+```yaml
+Type: Int32
+Parameter Sets: (All)
+Aliases:
+
+Required: False
+Position: 5
+Default value: 0
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
### -Tenant
Azure Active Directory (AAD) tenant id (Guid) that the D365FO environment is connected to, that you want to access through REST endpoint
@@ -130,7 +205,7 @@ Parameter Sets: (All)
Aliases: $AadGuid
Required: False
-Position: 4
+Position: 6
Default value: $Script:ODataTenant
Accept pipeline input: False
Accept wildcard characters: False
@@ -145,7 +220,7 @@ Parameter Sets: (All)
Aliases: Uri
Required: False
-Position: 5
+Position: 7
Default value: $Script:ODataUrl
Accept pipeline input: False
Accept wildcard characters: False
@@ -164,7 +239,7 @@ Parameter Sets: (All)
Aliases:
Required: False
-Position: 6
+Position: 8
Default value: $Script:ODataSystemUrl
Accept pipeline input: False
Accept wildcard characters: False
@@ -179,7 +254,7 @@ Parameter Sets: (All)
Aliases:
Required: False
-Position: 7
+Position: 9
Default value: $Script:ODataClientId
Accept pipeline input: False
Accept wildcard characters: False
@@ -194,7 +269,7 @@ Parameter Sets: (All)
Aliases:
Required: False
-Position: 8
+Position: 10
Default value: $Script:ODataClientSecret
Accept pipeline input: False
Accept wildcard characters: False
@@ -211,7 +286,7 @@ Parameter Sets: (All)
Aliases:
Required: False
-Position: 9
+Position: 11
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
@@ -246,7 +321,7 @@ Parameter Sets: (All)
Aliases:
Required: False
-Position: 10
+Position: 12
Default value: 0
Accept pipeline input: False
Accept wildcard characters: False