Azure / Azure/azure-functions-dotnet-worker
Avro payloads and full Kafka metadata access in the .NET 8 isolated model
- 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