Replies: 3 comments 2 replies
|
A sample protobuf message definition will look like this: syntax = "proto3";
message ErrorPayload {
uint32 schema_version = 1;
string message = 2;
oneof details {
PartitionNotFoundDetails partition_not_found = 10;
ResourceDetails resource = 11;
ChecksumDetails checksum = 12;
}
}
message PartitionNotFoundDetails {
uint64 partition_id = 1;
Identifier topic_id = 2;
Identifier stream_id = 3;
}
message Identifier {
oneof value {
uint32 id = 1;
string name = 2;
}
} |
|
Few quick thoughts: In my opinion, we should go to option B. I'm not sure if we need Apache.Fury (I don't know it, I need to check it out). Server also has to send every field value and rendered message from server (like in http). This means we don't need to store message templates in every sdk, and we also have way to get all parts of field values like topic_id, stream_id (like in your example protobuf). |
|
After discussion with the core team, it has been decided that we will postpone the error protocol implementation until the VSR cluster feature is stable. This proposal can be used for tracking and further discussion. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Problem
Issue raised by #3735
When the Iggy server rejects a request, the binary protocol response carries only a
4-byte discriminant (e.g.,
3007forPartitionNotFound). The actual field values(partition ID, topic ID, stream ID) are discarded before hitting the wire:
Due to
&[]payload insend_error_response<T>incore/server/src/sender/mod.rshere:iggy/core/server/src/sender/mod.rs
Lines 199 to 207 in d9635b6
Every data-bearing
IggyErrorvariant (StreamIdNotFound,TopicIdNotFound,InvalidOffset,ClientNotFound, …) arrives with zeroed or empty fields. Twogenuinely different requests produce byte-identical errors. The HTTP transport is
unaffected (it serializes
error.to_string()as JSONreason), proving the dataexists and is merely not transported.
Current SDK behavior
Each SDK handles the
[status:4][length:4][body:N]response frame independently,with widely varying treatment of the error body:
IggyError→ formatted stringstd::runtime_errorIggyInvalidStatusCodeExceptionIggyErrorstructs (code only)IggyServerException+ typed subclassesErrorIggyError→ PHP exceptionIggyError→RuntimeError(e.to_string())RuntimeError(undifferentiated)Three SDKS do their own parsing (C#, Go, Java). Four delegate to Rust (C++, Python,
PHP, Node via different approaches). The body contents are currently unused in
practice because the server sends an empty payload.
Proposed approaches
Option A — String payload (lightweight)
The server sends
error.to_string()as the response body:Pros
Go and Node.js need only to consume or surface the body bytes.
PartitionNotFoundfromInvalidOffset, etc.).Cons
PartitionNotFoundobject withpartition_id=5) from a flat string. For most use cases (logging, debug output), the human-readable string is sufficient.Option B — Structured serialization (full fidelity)
Define a wire-format specification that carries the error's fields as structured binary data, enabling callers to reconstruct the original typed error with every field populated.
Two sub-options:
B1. Custom specification
Define a simple binary layout (e.g., field-order matches the variant's tuple fields, integers as LE bytes, identifiers as
[kind:u8][len:u8][bytes]). This is what was prototyped in #3751.Pros: No external dependency. Full control over the wire format.
Cons: Must be manually reimplemented in every SDK that does its own wire parsing (C#, Go, Java, Node.js). Requires a specification document. Every new error variant must be added to the spec and each implementation.
B2. Standard serialization framework
Use a cross-language framework such as protobuf (already used in the connectors module) or Apache Fury to serialize error payloads.
Pros: Code generation for all target languages. Schema serves as documentation. No hand-written parser maintenance.
Cons: Introduces a dependency to every SDK. Serialization overhead for small error payloads (~20–80 bytes). Protobuf/Avro schema must be kept in sync with
IggyErrorvariants.Questions for discussion
Is full structured error reconstruction necessary? In practice, are callers inspecting error field values (e.g., the rejected partition ID) in application logic, or is the human-readable message sufficient?
If structured, B1 (custom) or B2 (framework)? Protobuf is already a transitive dependency via connectors. Would adding it to the error path be acceptable, or is a lightweight custom spec preferred?
Backward compatibility. Option A requires no changes to Java and C# (they already decode UTF-8 bodies). Option B requires changes to ALL self-parsing SDKs (C#, Go, Java, Node.js). Is the additional fidelity worth the per-SDK implementation cost?
Related Issues and PRs
IggyErrorinto an dedicated crate. #2524All reactions