Skip to content

Commit 964747a

Browse files
authored
Address bug bash reports (#53)
1 parent 726f5d0 commit 964747a

File tree

13 files changed

+200
-8
lines changed

13 files changed

+200
-8
lines changed

src/AzureFunctions.PowerShell.Durable.SDK.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# RootModule = ''
55

66
# Version number of this module.
7-
ModuleVersion = '0.0.1'
7+
ModuleVersion = '0.0.2'
88

99
# Supported PSEditions
1010
CompatiblePSEditions = @('Core')

src/AzureFunctions.PowerShell.Durable.SDK.psm1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ function Start-DurableOrchestration {
128128
$UriTemplate.Replace('{functionName}', $FunctionName).Replace('[/{instanceId}]', "/$InstanceId")
129129
}
130130

131-
$Body = $InputObject | ConvertTo-Json -Compress
131+
$Body = $InputObject | ConvertTo-Json -Compress -Depth 100
132132

133133
$null = Invoke-RestMethod -Uri $Uri -Method 'POST' -ContentType 'application/json' -Body $Body
134134

@@ -202,7 +202,7 @@ function New-DurableOrchestrationCheckStatusResponse {
202202
$requestHasValidUrl = IsValidUrl $requestUrl
203203
$requestUrlOrigin = GetUrlOrigin $requestUrl
204204

205-
$httpManagementPayload = @{ }
205+
$httpManagementPayload = [ordered]@{ }
206206
foreach ($entry in $DurableClient.managementUrls.GetEnumerator()) {
207207
$value = $entry.Value
208208

@@ -279,7 +279,7 @@ function Send-DurableExternalEvent {
279279

280280
$RequestUrl = GetRaiseEventUrl -DurableClient $DurableClient -InstanceId $InstanceId -EventName $EventName -TaskHubName $TaskHubName -ConnectionName $ConnectionName
281281

282-
$Body = $EventData | ConvertTo-Json -Compress
282+
$Body = $EventData | ConvertTo-Json -Compress -Depth 100
283283

284284
$null = Invoke-RestMethod -Uri $RequestUrl -Method 'POST' -ContentType 'application/json' -Body $Body
285285
}

src/DurableEngine/Tasks/DurableTask.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Collections;
44
using System.Management.Automation;
55
using System.Threading.Tasks;
6-
using static System.Collections.Specialized.BitVector32;
76

87
namespace DurableEngine.Tasks
98
{

src/DurableEngine/Utilities/DTFxUtilities.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using Microsoft.DurableTask;
2-
using Newtonsoft.Json;
2+
using Microsoft.PowerShell.Commands;
33
using System;
44
using System.Collections.Generic;
55

@@ -19,13 +19,20 @@ internal JsonDataConverter()
1919
/// <inheritdoc/>
2020
public override string Serialize(object value)
2121
{
22-
return value != null ? JsonConvert.SerializeObject(value) : null;
22+
// JsonObject is used here rather than JsonConvert because of a shared dependency with the PowerShell worker.
23+
// If the PowerShell worker ever changes the JSON serializer, then this repository would need to align with that.
24+
var context = new JsonObject.ConvertToJsonContext(
25+
maxDepth: 100,
26+
enumsAsStrings: false,
27+
compressOutput: true);
28+
29+
return value != null ? JsonObject.ConvertToJson(value, context) : null;
2330
}
2431

2532
/// <inheritdoc/>
2633
public override object Deserialize(string data, Type targetType)
2734
{
28-
return data != null ? JsonConvert.DeserializeObject(data, targetType) : null;
35+
return data != null ? JsonObject.ConvertFromJson(data, error: out _) : null;
2936
}
3037
}
3138

test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using AzureFunctions.PowerShell.Durable.SDK.Tests.E2E;
5+
using Newtonsoft.Json;
56
using System.Net;
67
using Xunit;
78

@@ -87,6 +88,86 @@ await ValidateDurableWorkflowResults(
8788
});
8889
}
8990

91+
[Fact]
92+
public async Task OrchestratorCanReceiveArrayFromActivity()
93+
{
94+
var initialResponse = await Utilities.GetHttpStartResponse("CanReceiveArrayOrchestrator");
95+
Assert.Equal(HttpStatusCode.Accepted, initialResponse.StatusCode);
96+
97+
var location = initialResponse.Headers.Location;
98+
Assert.NotNull(location);
99+
100+
await ValidateDurableWorkflowResults(
101+
initialResponse,
102+
validateInitialResponse: (dynamic initialStatusResponseBody) =>
103+
{
104+
Assert.NotNull(initialStatusResponseBody.id);
105+
var statusQueryGetUri = (string)initialStatusResponseBody.statusQueryGetUri;
106+
Assert.Equal(location?.ToString(), statusQueryGetUri);
107+
Assert.NotNull(initialStatusResponseBody.sendEventPostUri);
108+
Assert.NotNull(initialStatusResponseBody.purgeHistoryDeleteUri);
109+
Assert.NotNull(initialStatusResponseBody.terminatePostUri);
110+
Assert.NotNull(initialStatusResponseBody.rewindPostUri);
111+
},
112+
validateIntermediateResponse: (dynamic intermediateStatusResponseBody) =>
113+
{
114+
var runtimeStatus = (string)intermediateStatusResponseBody.runtimeStatus;
115+
Assert.True(
116+
runtimeStatus == "Running" || runtimeStatus == "Pending",
117+
$"Unexpected runtime status: {runtimeStatus}");
118+
},
119+
validateFinalResponse: (dynamic finalStatusResponseBody) =>
120+
{
121+
Assert.Equal("Completed", (string)finalStatusResponseBody.runtimeStatus);
122+
Assert.Equal("An", finalStatusResponseBody.output[0].ToString());
123+
Assert.Equal("Array", finalStatusResponseBody.output[1].ToString());
124+
});
125+
}
126+
127+
[Fact]
128+
public async Task CanReceiveDeeplyNestedClientInput()
129+
{
130+
var initialResponse = await Utilities.GetHttpStartResponse("OrchestratorReturnInput", clientRoute: "orchestratorsSendComplexInput");
131+
Assert.Equal(HttpStatusCode.Accepted, initialResponse.StatusCode);
132+
133+
var location = initialResponse.Headers.Location;
134+
Assert.NotNull(location);
135+
136+
await ValidateDurableWorkflowResults(
137+
initialResponse,
138+
validateInitialResponse: (dynamic initialStatusResponseBody) =>
139+
{
140+
Assert.NotNull(initialStatusResponseBody.id);
141+
var statusQueryGetUri = (string)initialStatusResponseBody.statusQueryGetUri;
142+
Assert.Equal(location?.ToString(), statusQueryGetUri);
143+
Assert.NotNull(initialStatusResponseBody.sendEventPostUri);
144+
Assert.NotNull(initialStatusResponseBody.purgeHistoryDeleteUri);
145+
Assert.NotNull(initialStatusResponseBody.terminatePostUri);
146+
Assert.NotNull(initialStatusResponseBody.rewindPostUri);
147+
},
148+
validateIntermediateResponse: (dynamic intermediateStatusResponseBody) =>
149+
{
150+
var runtimeStatus = (string)intermediateStatusResponseBody.runtimeStatus;
151+
Assert.True(
152+
runtimeStatus == "Running" || runtimeStatus == "Pending",
153+
$"Unexpected runtime status: {runtimeStatus}");
154+
},
155+
validateFinalResponse: (dynamic finalStatusResponseBody) =>
156+
{
157+
Assert.Equal("Completed", (string)finalStatusResponseBody.runtimeStatus);
158+
// our input is a JSON 7 levels deep, with a number on each level.
159+
// We check an integer for evidence of each level being preserved
160+
string inputStr = finalStatusResponseBody.input.ToString();
161+
Assert.Contains("1", inputStr);
162+
Assert.Contains("2", inputStr);
163+
Assert.Contains("3", inputStr);
164+
Assert.Contains("4", inputStr);
165+
Assert.Contains("5", inputStr);
166+
Assert.Contains("6", inputStr);
167+
Assert.Contains("7", inputStr);
168+
});
169+
}
170+
90171
[Fact]
91172
public async Task DurableClientTerminatesOrchestration()
92173
{
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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using namespace System.Net
2+
3+
param($Context)
4+
5+
$ErrorActionPreference = 'Stop'
6+
7+
$output = Invoke-DurableActivity -FunctionName "GetArrayActivity"
8+
return $output
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"bindings": [
3+
{
4+
"authLevel": "function",
5+
"name": "Request",
6+
"type": "httpTrigger",
7+
"direction": "in",
8+
"route": "orchestratorsSendComplexInput/{FunctionName}",
9+
"methods": [
10+
"post",
11+
"get"
12+
]
13+
},
14+
{
15+
"type": "http",
16+
"direction": "out",
17+
"name": "Response"
18+
},
19+
{
20+
"name": "starter",
21+
"type": "durableClient",
22+
"direction": "in"
23+
}
24+
]
25+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using namespace System.Net
2+
3+
param($Request, $TriggerMetadata)
4+
$ErrorActionPreference = 'Stop'
5+
6+
Write-Host "DurableClient started"
7+
8+
$FunctionName = $Request.Params.FunctionName
9+
10+
$Input = @{
11+
"1" = @{
12+
"2" = @{
13+
"3" = @{
14+
"4" = @{
15+
"5" = @{
16+
"6" = 7
17+
}
18+
}
19+
}
20+
}
21+
}
22+
}
23+
$InstanceId = Start-DurableOrchestration -FunctionName $FunctionName -Input $Input
24+
Write-Host "Started orchestration with ID = '$InstanceId'"
25+
26+
$Response = New-DurableOrchestrationCheckStatusResponse -Request $Request -InstanceId $InstanceId
27+
Push-OutputBinding -Name Response -Value $Response
28+
29+
$Status = Get-DurableStatus -InstanceId $InstanceId
30+
Write-Host "Orchestration $InstanceId status: $($Status | ConvertTo-Json)"
31+
if ($Status.RuntimeStatus -notin 'Pending', 'Running', 'Failed', 'Completed') {
32+
throw "Unexpected orchestration $InstanceId runtime status: $($Status.RuntimeStatus)"
33+
}
34+
35+
Write-Host "DurableClient completed"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"bindings": [
3+
{
4+
"name": "name",
5+
"type": "activityTrigger",
6+
"direction": "in"
7+
}
8+
]
9+
}

0 commit comments

Comments
 (0)