Azure / Azure/azure-functions-host
Custom Trigger/Binding Serialization in Isolated worker
- Dominant language
- C#
- Stars
- 2k
- Forks
- 482
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 38
Description
This applies to v4 Isolated Worker Functions
Languages: C#
In our organization, we have developed a Custom Trigger/Output Bindings extension for one of the major message brokers that don't currently have support for Azure Functions out of the box, that allows us to use the functions to send/receive to their queues/topics. We have being using this extension successfully for the last couple of years.
One of the major features of the extension is to deserialize/serialize the payload base on custom types provided by the function's method signature. We currently support sending/receiving ```string```, ```byte[]``` and ```POCO``` classes. The extension provides JSON serialization by default, but it's replaceable by implementing an interface and registering the instance with DI. We have cases where serialization is AVRO, for example.
In the hosted model, everything works as expected, because the serializer that's registered with the custom trigger is in the same process, and has access to the runtime type specified by the function signature. In the Isolated model, this is not the case since the custom trigger would run on the host and the function signature would be on another process.
We would like for the custom trigger to support the Isolated model, but we've found no way to go forward with this, the trigger in the host only receives either a byte[] or a JSON serialized representation of the object.
For reference I'm including a pseudo-code snippet of how a function signature would look, the ```Message``` class is defined in the extension, ```CustomPoco``` is defined in the Isolated Functions project:
```
[Function("FunctionName")]
[CustomBindingOutput]
public Message MyFunctionName([CustomTrigger(Queue = "my-queue")] CustomPoco payload)
{
...
return new Message("destination-topic-or-queue", payload);
}
```
The extension uses whichever serializer is registered in the DI container with interfaces like this:
```
public interface IInputSerializer
{
T ReadObject(byte[] input);
}
```
and
```
public interface IOutputSerializer
{
byte[] WriteObject(T input);
}
```
That allows us to provide a default serializer but also let the consumer register their own if needed. We also access other properties of the ```Message``` class for headers, etc.
I would like to understand what would be the path forward to support this type of scenario for developing custom extensions, for either triggers and output bindings.
Contributor guide
Research direction
Start by tracing the isolated-worker boundary described between CustomTrigger/CustomBindingOutput and the function signature, then review how IInputSerializer and IOutputSerializer are registered and invoked. The issue names no repository files or tests; done would require an agreed design for carrying custom type and serializer information across the host/worker boundary for trigger and output-binding scenarios.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, csharp
- Domain
- backend, cloud
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100