PowerShell Durable Function Activity Bindings with Table Bindings
Opened this issue · 6 comments
Discussed in #2904
Originally posted by Bionic711 August 28, 2024
I am currently working on a Durable Function written in PowerShell and having issues passing the input of the activityTrigger to the rowKey of a Table input in the same activity. {input}
from the name of the activity trigger allows it to run, and logs show it was passed ["stringvalue"]
, but using the type as described in MSFT docs with the queue trigger does not. {activityTrigger}
results in a 'not recognized as a named parameter' error. The interesting part is that when it reaches out to the table to pull the value when using {input}
, it says that the rowKey or partitionKey cannot be ''.
Thus far I have only tested locally with Azurite as the emulator.
Any ideas how to get this to work?
@andystaples would you happen to know the answer to this?
Here is the bindings:
{
"bindings": [
{
"name": "input",
"type": "activityTrigger",
"direction": "in"
},
{
"name": "mailbox",
"type": "table",
"tableName": "mailboxes",
"partitionKey": "mailboxes",
"rowKey": "{input}",
"connection": "AzureWebJobsStorage",
"direction": "in"
},
{
"name": "results",
"type": "table",
"tableName": "results",
"connection": "AzureWebJobsStorage",
"direction": "out"
}
],
"disabled": false
}
Thanks for reaching out @Bionic711. This is the first time I hear of symptoms like this so we'll need to reproduce this in our end to dive deeper. Do you have a minimal reproducer you could share with us?
I spoke with @davidmrdavid and will be uploading a reproducer by mid next week.
This replicates the issue locally for me.
BaseTimer Function:
param($Timer, $TriggerMetadata)
$InstanceId = Start-DurableOrchestration -FunctionName "Orchestrator"
Write-Host "Started orchestration with ID = '$InstanceId'"
{
"bindings": [
{
"name": "Timer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 0 0 * * *",
"runOnStartup": true
},
{
"name": "starter",
"type": "durableClient",
"direction": "in"
}
],
"scriptFile": "run.ps1"
}
Orchestrator Function:
param($Orchestrator, $TriggerMetadata)
$context = $TriggerMetadata
$results = Invoke-DurableActivity -FunctionName "Query"
$retryOptions = New-DurableRetryOptions `
-FirstRetryInterval (New-Timespan -Seconds 5) `
-MaxNumberOfAttempts 1
$parallelTasks = @()
$parallelTasks =
foreach ($upn in $results.UPNs) {
#Write-Host "Now creating task for $upn"
Invoke-DurableActivity -FunctionName 'Permissions' -Input $upn -NoWait -RetryOptions $retryOptions
}
$output = Wait-DurableTask -Task $parallelTasks
{
"bindings": [
{
"name": "Orchestrator",
"type": "orchestrationTrigger",
"direction": "in"
}
]
}
Query Function:
param($input, $TriggerMetadata)
$context = $TriggerMetadata
$upns = New-Object System.Collections.Generic.List[String]
$Mbxs = @(
[PSCustomObject]@{
UserPrinicpalName = 'john.doe@contoso.com'
DisplayName = 'John Doe'
FirstName = 'John'
LastName = 'Doe'
},
[PSCustomObject]@{
UserPrinicpalName = 'jane.smith@contoso.com'
DisplayName = 'Jane Smith'
FirstName = 'Jane'
LastName = 'Smith'
},
[PSCustomObject]@{
UserPrinicpalName = 'michael.brown@contoso.com'
DisplayName = 'Michael Brown'
FirstName = 'Michael'
LastName = 'Brown'
},
[PSCustomObject]@{
UserPrinicpalName = 'emily.johnson@contoso.com'
DisplayName = 'Emily Johnson'
FirstName = 'Emily'
LastName = 'Johnson'
},
[PSCustomObject]@{
UserPrinicpalName = 'david.williams@contoso.com'
DisplayName = 'David Williams'
FirstName = 'David'
LastName = 'Williams'
},
[PSCustomObject]@{
UserPrinicpalName = 'sarah.jones@contoso.com'
DisplayName = 'Sarah Jones'
FirstName = 'Sarah'
LastName = 'Jones'
},
[PSCustomObject]@{
UserPrinicpalName = 'chris.miller@contoso.com'
DisplayName = 'Chris Miller'
FirstName = 'Chris'
LastName = 'Miller'
},
[PSCustomObject]@{
UserPrinicpalName = 'laura.davis@contoso.com'
DisplayName = 'Laura Davis'
FirstName = 'Laura'
LastName = 'Davis'
},
[PSCustomObject]@{
UserPrinicpalName = 'kevin.garcia@contoso.com'
DisplayName = 'Kevin Garcia'
FirstName = 'Kevin'
LastName = 'Garcia'
},
[PSCustomObject]@{
UserPrinicpalName = 'linda.martinez@contoso.com'
DisplayName = 'Linda Martinez'
FirstName = 'Linda'
LastName = 'Martinez'
},
[PSCustomObject]@{
UserPrinicpalName = 'steven.rodriguez@contoso.com'
DisplayName = 'Steven Rodriguez'
FirstName = 'Steven'
LastName = 'Rodriguez'
},
[PSCustomObject]@{
UserPrinicpalName = 'karen.hernandez@contoso.com'
DisplayName = 'Karen Hernandez'
FirstName = 'Karen'
LastName = 'Hernandez'
},
[PSCustomObject]@{
UserPrinicpalName = 'brian.lopez@contoso.com'
DisplayName = 'Brian Lopez'
FirstName = 'Brian'
LastName = 'Lopez'
},
[PSCustomObject]@{
UserPrinicpalName = 'nancy.gonzalez@contoso.com'
DisplayName = 'Nancy Gonzalez'
FirstName = 'Nancy'
LastName = 'Gonzalez'
},
[PSCustomObject]@{
UserPrinicpalName = 'joshua.wilson@contoso.com'
DisplayName = 'Joshua Wilson'
FirstName = 'Joshua'
LastName = 'Wilson'
},
[PSCustomObject]@{
UserPrinicpalName = 'betty.anderson@contoso.com'
DisplayName = 'Betty Anderson'
FirstName = 'Betty'
LastName = 'Anderson'
},
[PSCustomObject]@{
UserPrinicpalName = 'mark.thomas@contoso.com'
DisplayName = 'Mark Thomas'
FirstName = 'Mark'
LastName = 'Thomas'
},
[PSCustomObject]@{
UserPrinicpalName = 'patricia.taylor@contoso.com'
DisplayName = 'Patricia Taylor'
FirstName = 'Patricia'
LastName = 'Taylor'
},
[PSCustomObject]@{
UserPrinicpalName = 'paul.moore@contoso.com'
DisplayName = 'Paul Moore'
FirstName = 'Paul'
LastName = 'Moore'
},
[PSCustomObject]@{
UserPrinicpalName = 'jennifer.jackson@contoso.com'
DisplayName = 'Jennifer Jackson'
FirstName = 'Jennifer'
LastName = 'Jackson'
},
[PSCustomObject]@{
UserPrinicpalName = 'george.white@contoso.com'
DisplayName = 'George White'
FirstName = 'George'
LastName = 'White'
},
[PSCustomObject]@{
UserPrinicpalName = 'maria.harris@contoso.com'
DisplayName = 'Maria Harris'
FirstName = 'Maria'
LastName = 'Harris'
},
[PSCustomObject]@{
UserPrinicpalName = 'frank.martin@contoso.com'
DisplayName = 'Frank Martin'
FirstName = 'Frank'
LastName = 'Martin'
},
[PSCustomObject]@{
UserPrinicpalName = 'susan.thompson@contoso.com'
DisplayName = 'Susan Thompson'
FirstName = 'Susan'
LastName = 'Thompson'
},
[PSCustomObject]@{
UserPrinicpalName = 'jason.garcia@contoso.com'
DisplayName = 'Jason Garcia'
FirstName = 'Jason'
LastName = 'Garcia'
},
[PSCustomObject]@{
UserPrinicpalName = 'dorothy.martinez@contoso.com'
DisplayName = 'Dorothy Martinez'
FirstName = 'Dorothy'
LastName = 'Martinez'
},
[PSCustomObject]@{
UserPrinicpalName = 'gregory.robinson@contoso.com'
DisplayName = 'Gregory Robinson'
FirstName = 'Gregory'
LastName = 'Robinson'
}
)
foreach ($Mbx in $($Mbxs | Select -First 50))
{
try {
Push-OutputBinding -Name "mailboxes" -Value @{
ETag = "*"
PartitionKey = "mailboxes"
RowKey = $Mbx.UserPrincipalName
DisplayName = $Mbx.DisplayName
UserPrincipalName = $Mbx.UserPrincipalName
FirstName = $Mbx.FirstName
LastName = $Mbx.LastName
}
}
catch {
if ($_.Exception.Response.StatusCode -eq 409) {
Write-Host "409 Conflict Error: The resource already exists or cannot be created in its current state."
}
else {
# Handle other errors
Write-Error "An unexpected error occurred: $($_.Exception.Message)"
}
}
if ([string]::IsNullOrEmpty($Mbx.UserPrincipalName))
{
Write-Host "Empty UserPrincipalName for $($Mbx.DisplayName)"
}
else
{
$upns.Add($Mbx.UserPrincipalName)
}
}
$output = [PSCustomObject]@{
UPNs = $upns
TotalCount = $totalCount
}
return $output
{
"bindings": [
{
"name": "input",
"type": "activityTrigger",
"direction": "in"
},
{
"name": "mailboxes",
"type": "table",
"tableName": "mailboxes",
"connection": "AzureWebJobsStorage",
"direction": "out"
}
],
"scriptFile": "run.ps1"
}
Permissions Function (where the issue is at):
param($input, $mailbox, $TriggerMetadata)
$context = $TriggerMetadata
Write-Host "`nPermissions received input: $($input)"
{
"bindings": [
{
"name": "input",
"type": "activityTrigger",
"direction": "in"
},
{
"name": "mailbox",
"type": "table",
"tableName": "mailboxes",
"partitionKey": "mailboxes",
"rowKey": "{input}",
"connection": "AzureWebJobsStorage",
"direction": "in"
},
{
"name": "results",
"type": "table",
"tableName": "results",
"connection": "AzureWebJobsStorage",
"direction": "out"
}
],
"disabled": false
}
Host.json
{
"version": "2.0",
"extensions": {
"durableTask": {
"hubName": "ExchangePermissionsHub",
"maxConcurrentActivityFunctions": 20,
"maxConcurrentOrchestratorFunctions": 1,
"storeInputsInOrchestrationHistory": true,
"traceInputsAndOutputs": true
}
},
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
},
"managedDependency": {
"enabled": true
},
"functionTimeout": "-1"
}
This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.