Azure / Azure/azure-functions-dotnet-worker

Avro payloads and full Kafka metadata access in the .NET 8 isolated model

Open
#3,128 1 comment 0 reactions 0 assignees View on GitHub
enhancement Needs: Triage (Functions)
Dominant language
C#
Stars
466
Forks
215
Avg merge
3d 10h
Merged PRs (30d)
7

Description

### Description

In the in-process model of Kafka-triggered Azure Functions, we were able to access Kafka message metadata such as headers, topic, offset, key, and value using the KafkaEventData parameter. However, in the .NET 8 isolated worker model, this has been replaced by string or string[], which currently supports only JSON payloads.
Our use case involves Avro payloads, and we require full access to Kafka message metadata, including key, value, and headers. The Kafka producer sends the key and value separately, not embedded within the payload. We attempted to use byte[] as the parameter type, and while the message can be consumed when the Avro schema is explicitly defined in the binding properties, the key retrieved from the function context appears as a malformed string and cannot be deserialized properly. Additionally, the headers seem to be double base64 encoded, making them difficult to interpret.
We would greatly appreciate enhanced support for Avro payloads and full Kafka metadata access in the .NET 8 isolated model for Azure Functions. This would enable more robust and flexible event processing scenarios.

Below is the our Avro schema:

{
"fields": [
{
"default": null,
"doc": "Current chunk number of this message.",
"name": "Chunk_Number",
"type": [
"null",
"int"
]
},
{
"default": null,
"doc": "Represents total count of chunks to expect for this message.",
"name": "Total_No_Of_Chunks",
"type": [
"null",
"int"
]
},
{
"doc": "Curve publish type - EOD or LIVE.",
"name": "Publish_Curve_Type",
"type": "string"
},
{
"doc": "Name of the commodity for which price/value is given.",
"name": "Commodity",
"type": "string"
},
{
"default": null,
"doc": "",
"name": "Commodity_Delivery_Point",
"type": [
"null",
"string"
]
},
{
"default": null,
"doc": "Only applicable for Power",
"name": "Commodity_Profile",
"type": [
"null",
"string"
]
},
{
"doc": "Curreny in which price/value is provided. ",
"name": "Currency1",
"type": "string"
},
{
"default": null,
"doc": "Only applicable in case of FX.",
"name": "Currency2",
"type": [
"null",
"string"
]
},
{
"doc": "Unique identifier for a curve in current system",
"name": "Curve_Id",
"type": "string"
},
{
"default": null,
"doc": "Name of the Curve as defined in current system",
"name": "Curve_Name",
"type": [
"null",
"string"
]
},
{
"default": null,
"doc": "Unique identifier in source system for a curve",
"name": "Source_Curve_Id",
"type": [
"null",
"string"
]
},
{
"default": null,
"doc": "Name of the curve defined in source system",
"name": "Source_Curve_Name",
"type": [
"null",
"string"
]
},
{
"doc": "Type of Curve.",
"name": "Curve_Type",
"type": "string"
},
{
"doc": "Name of the data provider for the curve prices/values.",
"name": "Data_Provider",
"type": [
"null",
"string"
]
},
{
"doc": "Period interval for the price/value point.",
"name": "Granularity",
"type": "string"
},
{
"default": null,
"doc": "Market Location.",
"name": "Location",
"type": [
"null",
"string"
]
},
{
"default": null,
"doc": "Timezone Identifier in which source application is sending price/value points",
"name": "TimeZone_Identifier",
"type": [
"null",
"string"
]
},
{
"doc": "Types of Prices for Curves.",
"name": "Price_Type",
"type": "string"
},
{
"doc": "True if curve is licenced to specific entity",
"name": "Private_Indicator",
"type": "boolean"
},
{
"default": null,
"doc": "Buy the underlying commodity(in the case of a call option). Sell the underlying commodity(in the case of a put option). e.g. 'Call','Put'",
"name": "Put_Call",
"type": [
"null",
"string"
]
},
{
"doc": "Name of the source system where curve is built.",
"name": "Source_Application",
"type": "string"
},
{
"doc": "Name of the current system from where this curve is being served.",
"name": "Application_Name",
"type": "string"
},
{
"doc": "Unit of measure for the commodity.",
"name": "UOM",
"type": "string"
},
{
"default": null,
"doc": "Placeholder for additional key value pair(s), e.g Commodity_Subgroup.",
"name": "Curve_Metadata",
"type": [
"null",
{
"type": "map",
"values": "string"
}
]
},
{
"default": null,
"doc": "A payload can have multiple instances of the curve",
"name": "Curve_Instances",
"type": [
"null",
{
"items": [
"null",
{
"fields": [
{
"default": null,
"name": "Curve_Values",
"type": [
"null",
{
"items": [
"null",
{
"fields": [
{
"doc": "Value of this timeseries",
"name": "Value",
"type": "double"
},
{
"doc": "DateTime till which the curve value is applicable",
"name": "Period_End_DateTime",
"type": {
"logicalType": "timestamp-micros",
"type": "long"
}
},
{
"doc": "DateTime from which the curve value is applicable",
"name": "Period_Start_DateTime",
"type": {
"logicalType": "timestamp-micros",
"type": "long"
}
},
{
"default": null,
"doc": "Unique identifier for curve price/value points",
"name": "Price_Point_Id",
"type": [
"null",
"int"
]
},
{
"default": null,
"doc": "",
"name": "Strike_Price",
"type": [
"null",
"double"
]
},
{
"default": null,
"doc": "Placeholder for additional key value pair(s),",
"name": "Price_Point_Metadata",
"type": [
"null",
{
"type": "map",
"values": "string"
}
]
}
],
"name": "Curve_Value",
"type": "record"
}
],
"type": "array"
}
]
},
{
"doc": "Business Date when Curve published",
"name": "Effective_Date",
"type": {
"logicalType": "date",
"type": "int"
}
},
{
"doc": "Source System Date when the prices/values was updated in Source system, this is in UTC timezone.",
"name": "Source_Updated_DateTime",
"type": {
"logicalType": "timestamp-micros",
"type": "long"
}
},
{
"default": null,
"doc": "DateTime at which Trader approves the curve",
"name": "Trader_Approval_DateTime_UTC",
"type": [
"null",
{
"logicalType": "timestamp-micros",
"type": "long"
}
]
},
{
"default": null,
"doc": "Indicator to identify if the Curve is approved by Trader or not",
"name": "Trader_Approval_Indicator",
"type": [
"null",
"boolean"
]
},
{
"default": null,
"doc": "Name of the Trader who approves the curve",
"name": "Trader_Approval_Name",
"type": [
"null",
"string"
]
},
{
"doc": "System updated timestamp in UTC from where this curve is published (e.g. PCB, PDS)",
"name": "Last_Updated_DateTime_UTC",
"type": {
"logicalType": "timestamp-micros",
"type": "long"
}
},
{
"default": null,
"doc": "Placeholder for additional key value pair(s) for technical field.",
"name": "Additional_Metadata",
"type": [
"null",
{
"type": "map",
"values": "string"
}
]
},
{
"default": null,
"doc": "Unique identifier for a curve instance/version",
"name": "Curve_Build_Id",
"type": [
"null",
"string"
]
}
],
"name": "Curve_Instance",
"type": "record"
},
{
"fields": [
{
"default": null,
"doc": "Unique resource identifier link, making a GET call should return the payload of this instance.",
"name": "URL",
"type": [
"null",
"string"
]
}
],
"name": "Curve_Instance_Notification",
"type": "record"
}
],
"type": "array"
}
]
}
],
"name": "Curve_Data",
"namespace": "Pricing.Model",
"type": "record"
}

////schema for Key

{
"fields": [
{
"doc": "Name of the current system from where this curve is being served",
"name": "Application_Name",
"type": "string"
},
{
"doc": "Unique curve identifier in current system.",
"name": "Curve_Id",
"type": "string"
},
{
"default": false,
"doc": "Represents whether this message is chunked in parts.",
"name": "Is_Chunked",
"type": "boolean"
}
],
"name": "Curve_Key",
"namespace": "Pricing.Model",
"type": "record"
}

Contributor guide

No contributing guide indexed for this repository

Research direction

No repository files or tests are named. Start by tracing the .NET 8 isolated Kafka binding and how the function context exposes key, value, and headers, then reproduce the behavior with the supplied Avro payload and key schemas. Done means Avro payloads and complete Kafka metadata are accessible without malformed keys or double-encoded headers.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, csharp, kafka
Domain
backend, cloud, distributed-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.