Skip to content

Commit 463f794

Browse files
authored
Allow DF Activity Functions to have multiple output bindings (#703)
1 parent 9b3c1c8 commit 463f794

File tree

8 files changed

+90
-2
lines changed

8 files changed

+90
-2
lines changed

release_notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* Bug fix: Activity Functions can now use output bindings (https://github.com/Azure/azure-functions-powershell-worker/issues/646)

src/RequestProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ private static TraceContext GetTraceContext(AzFunctionInfo functionInfo, Invocat
456456
/// </summary>
457457
private static void BindOutputFromResult(InvocationResponse response, AzFunctionInfo functionInfo, IDictionary results)
458458
{
459-
if (functionInfo.DurableFunctionInfo.Type == DurableFunctionType.None) // TODO: but let activity functions have output bindings, too
459+
if (functionInfo.DurableFunctionInfo.Type != DurableFunctionType.OrchestrationFunction)
460460
{
461461
// Set out binding data and return response to be sent back to host
462462
foreach (var (bindingName, bindingInfo) in functionInfo.OutputBindings)

test/E2E/Azure.Functions.PowerShellWorker.E2E/Azure.Functions.PowerShellWorker.E2E/DurableEndToEndTests.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,56 @@ public async Task LegacyDurableCommandNamesStillWork()
147147
}
148148
}
149149

150+
[Fact]
151+
public async Task ActivityCanHaveQueueBinding()
152+
{
153+
const string queueName = "outqueue";
154+
await StorageHelpers.ClearQueue(queueName);
155+
var initialResponse = await Utilities.GetHttpTriggerResponse("DurableClient", queryString: "?FunctionName=DurableOrchestratorWriteToQueue");
156+
Assert.Equal(HttpStatusCode.Accepted, initialResponse.StatusCode);
157+
158+
var initialResponseBody = await initialResponse.Content.ReadAsStringAsync();
159+
dynamic initialResponseBodyObject = JsonConvert.DeserializeObject(initialResponseBody);
160+
var statusQueryGetUri = (string)initialResponseBodyObject.statusQueryGetUri;
161+
162+
var startTime = DateTime.UtcNow;
163+
164+
using var httpClient = new HttpClient();
165+
166+
while (true)
167+
{
168+
var statusResponse = await httpClient.GetAsync(statusQueryGetUri);
169+
switch (statusResponse.StatusCode)
170+
{
171+
case HttpStatusCode.Accepted:
172+
{
173+
if (DateTime.UtcNow > startTime + _orchestrationCompletionTimeout)
174+
{
175+
Assert.True(false, $"The orchestration has not completed after {_orchestrationCompletionTimeout}");
176+
}
177+
178+
await Task.Delay(TimeSpan.FromSeconds(2));
179+
break;
180+
}
181+
182+
case HttpStatusCode.OK:
183+
{
184+
var statusResponseBody = await GetResponseBodyAsync(statusResponse);
185+
Assert.Equal("Completed", (string)statusResponseBody.runtimeStatus);
186+
187+
var queueMessage = await StorageHelpers.ReadFromQueue(queueName);
188+
Assert.Equal("QueueData", queueMessage);
189+
return;
190+
}
191+
192+
default:
193+
Assert.True(false, $"Unexpected orchestration status code: {statusResponse.StatusCode}");
194+
break;
195+
}
196+
}
197+
}
198+
199+
150200
[Fact]
151201
public async Task ActivityExceptionIsPropagatedThroughOrchestrator()
152202
{
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"bindings": [
3+
{
4+
"name": "name",
5+
"type": "activityTrigger",
6+
"direction": "in"
7+
},
8+
{
9+
"type": "queue",
10+
"direction": "out",
11+
"name": "outputQueueItem",
12+
"queueName": "outqueue",
13+
"connection": "AzureWebJobsStorage"
14+
}
15+
]
16+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
param($name)
2+
3+
Write-Information "Pushing to outputQueueItem output binding"
4+
Push-OutputBinding -Name outputQueueItem -Value $name
5+
Write-Information "Done"
6+
7+
"Hello $name!"

test/E2E/TestFunctionApp/DurableClient/run.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Push-OutputBinding -Name Response -Value $Response
1616

1717
$Status = Get-DurableStatus -InstanceId $InstanceId
1818
Write-Host "Orchestration $InstanceId status: $($Status | ConvertTo-Json)"
19-
if ($Status.runtimeStatus -notin 'Pending', 'Running', 'Failed') {
19+
if ($Status.runtimeStatus -notin 'Pending', 'Running', 'Failed', 'Completed') {
2020
throw "Unexpected orchestration $InstanceId runtime status: $($Status.runtimeStatus)"
2121
}
2222

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"bindings": [
3+
{
4+
"name": "Context",
5+
"type": "orchestrationTrigger",
6+
"direction": "in"
7+
}
8+
]
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using namespace System.Net
2+
3+
param($Context)
4+
5+
Invoke-DurableActivity -FunctionName 'DurableActivityWritesToQueue' -Input 'QueueData'

0 commit comments

Comments
 (0)