Skip to content

Commit

Permalink
Patch deserialization bug in 2.13.1 (#2745)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmrdavid authored Mar 13, 2024
1 parent e568610 commit 254b262
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,18 @@ internal object GetInput(Type destinationType)

string serializedValue = jToken.ToString(Formatting.None);

// Object inputs for out-of-proc activities are passed in their JSON-stringified form with a destination
// type of System.String. Unfortunately, deserializing a JSON string to a string causes
// MessagePayloadDataConverter to throw an exception. This is a workaround for that case. All other
// inputs with destination System.String (in-proc: JSON and not JSON; out-of-proc: not-JSON) inputs with
// destination System.String should cast to JValues and be handled above.)
if (this.rawInput)
if (this.rawInput) // the "modern" OOProc protocol case
{
return serializedValue;
}
else if (destinationType.Equals(typeof(string))) // legacy OOProc protocol case (JS, Python, PowerShell)
{
// Object/complex inputs in "legacy" out-of-proc activities are passed with a destination
// type of System.String (to be precise, if inspected with a debugger, you'll see a stringified JSON).
// Unfortunately, deserializing a JSON string to a string causes MessagePayloadDataConverter to throw an exception, so the
// return statement prevents that.
return serializedValue;
}

return this.messageDataConverter.Deserialize(serializedValue, destinationType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ const df = require("durable-functions");

module.exports = df.orchestrator(function* (context) {
const outputs = [];
const city = {city:"Paris", country:"France"};

// Replace "Hello" with the name of your Durable Activity Function.
outputs.push(yield context.df.callActivity("Hello", "Tokyo"));
outputs.push(yield context.df.callActivity("Hello", "Seattle"));
outputs.push(yield context.df.callActivity("Hello", "London"));
outputs.push(yield context.df.callActivity("Hello", 123));
outputs.push(yield context.df.callActivity("PrintArray", ["Dubai", "New York", "Vancouver"]));
outputs.push(yield context.df.callActivity("PrintObject", city));

// returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
return outputs;
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"bindings": [
{
"name": "array",
"type": "activityTrigger",
"direction": "in"
}
]
}
14 changes: 14 additions & 0 deletions test/SmokeTests/OOProcSmokeTests/durableJS/PrintArray/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* This function is not intended to be invoked directly. Instead it will be
* triggered by an orchestrator function.
*
* Before running this sample, please:
* - create a Durable orchestration function
* - create a Durable HTTP starter function
* - run 'npm install durable-functions' from the wwwroot folder of your
* function app in Kudu
*/

module.exports = async function (context) {
return context.bindings.array.toString();
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"bindings": [
{
"name": "cities",
"type": "activityTrigger",
"direction": "in"
}
]
}
14 changes: 14 additions & 0 deletions test/SmokeTests/OOProcSmokeTests/durableJS/PrintObject/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* This function is not intended to be invoked directly. Instead it will be
* triggered by an orchestrator function.
*
* Before running this sample, please:
* - create a Durable orchestration function
* - create a Durable HTTP starter function
* - run 'npm install durable-functions' from the wwwroot folder of your
* function app in Kudu
*/

module.exports = async function (context) {
return JSON.stringify(context.bindings.obj);
};
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ public String citiesOrchestrator(
@DurableOrchestrationTrigger(name = "orchestratorRequestProtoBytes") String orchestratorRequestProtoBytes) {
return OrchestrationRunner.loadAndRun(orchestratorRequestProtoBytes, ctx -> {
String result = "";
String[] cities = {"Dubai", "New York", "Vancouver"};
City paris = new City("France", "Paris");

result += ctx.callActivity("Capitalize", "Tokyo", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "London", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "Seattle", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "Austin", String.class).await();
result += ctx.callActivity("Capitalize", "Austin", String.class).await()+ ", ";

result += ctx.callActivity("Print", 123, String.class).await()+ ", ";
result += ctx.callActivity("PrintArray", cities, String.class).await()+ ", ";
result += ctx.callActivity("PrintObject", paris, String.class).await()+ ", ";

return result;
});
}
Expand All @@ -58,4 +66,59 @@ public String capitalize(
context.getLogger().info("Capitalizing: " + name);
return name.toUpperCase();
}

@FunctionName("Print")
public String print(
@DurableActivityTrigger(name = "input") String input,
final ExecutionContext context) {
context.getLogger().info("Printing input: " + input);
return input.toString();
}

@FunctionName("PrintArray")
public String printArray(
@DurableActivityTrigger(name = "array") String[] array,
final ExecutionContext context) {
context.getLogger().info(Arrays.toString(array));
return Arrays.toString(array);
}

@FunctionName("PrintObject")
public String printObject(
@DurableActivityTrigger(name = "city") City city,
final ExecutionContext context) {
context.getLogger().info("Printing object" + city.toString());
return city.toString();
}

public class City {
private String country;
private String name;

public City(String country, String name){
this.country = country;
this.name = name;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "City [Country=" + country + ", name=" + name + "]";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,34 @@
import azure.functions as func
import azure.durable_functions as df

class City:
def __init__(self, country, name):
self.country = country
self.name = name

def to_json(self):
return json.dumps({"name": self.name, "country": self.country})

@classmethod
def from_json(cls, json_str):
data = json.loads(json_str)
return cls(name=data['name'], country=data['country'])

def __str__(self):
return f"City(name= {self.name}, country= {self.country})"

def orchestrator_function(context: df.DurableOrchestrationContext):
result1 = yield context.call_activity('Hello', "Tokyo")
result2 = yield context.call_activity('Hello', "Seattle")
result3 = yield context.call_activity('Hello', "London")
return [result1, result2, result3]
result4 = yield context.call_activity('Print', 123)

cities = ["Tokyo", "Seattle", "Cairo"]
result5 = yield context.call_activity("PrintArray", cities)

city = City("France", "Paris")
result6 = yield context.call_activity("PrintObject", city)

return [result1, result2, result3, result4, result5, result6]

main = df.Orchestrator.create(orchestrator_function)
13 changes: 13 additions & 0 deletions test/SmokeTests/OOProcSmokeTests/durablePy/Print/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# This function is not intended to be invoked directly. Instead it will be
# triggered by an orchestrator function.
# Before running this sample, please:
# - create a Durable orchestration function
# - create a Durable HTTP starter function
# - add azure-functions-durable to requirements.txt
# - run pip install -r requirements.txt

import logging


def main(input: int) -> str:
return f"{input}"
10 changes: 10 additions & 0 deletions test/SmokeTests/OOProcSmokeTests/durablePy/Print/function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "input",
"type": "activityTrigger",
"direction": "in"
}
]
}
16 changes: 16 additions & 0 deletions test/SmokeTests/OOProcSmokeTests/durablePy/PrintArray/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This function is not intended to be invoked directly. Instead it will be
# triggered by an orchestrator function.
# Before running this sample, please:
# - create a Durable orchestration function
# - create a Durable HTTP starter function
# - add azure-functions-durable to requirements.txt
# - run pip install -r requirements.txt

import logging

def main(cities: list) -> str:
results = "";
for city in cities:
result = f"{city} "
results += result
return results
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "cities",
"type": "activityTrigger",
"direction": "in"
}
]
}
13 changes: 13 additions & 0 deletions test/SmokeTests/OOProcSmokeTests/durablePy/PrintObject/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# This function is not intended to be invoked directly. Instead it will be
# triggered by an orchestrator function.
# Before running this sample, please:
# - create a Durable orchestration function
# - create a Durable HTTP starter function
# - add azure-functions-durable to requirements.txt
# - run pip install -r requirements.txt

import logging


def main(obj: object) -> str:
return f"Printing object: {obj}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "obj",
"type": "activityTrigger",
"direction": "in"
}
]
}

0 comments on commit 254b262

Please sign in to comment.