[ 
https://issues.apache.org/jira/browse/KAFKA-7787?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17017873#comment-17017873
 ] 

Tom Bentley commented on KAFKA-7787:
------------------------------------

[~cmccabe] I was thinking about this and have a partially working 
implementation, but wanted your thoughts before I spend more time on it.

cc: [~hachikuji] who raised the original comment on the PR for the message 
generator.

The following approach works for all enum-like codes in the protocol, not just 
error codes.

h2. Declaring coded values

The generator will support a new kind of JSON object input {{"type": "codes"}}, 
which describes a set of distinct named integer (byte, short, etc) values. For 
example:
{code:language=js}
{
  "type": "codes",
  "name": "ErrorCodes",
  "valueType": "int16"
  "codes": [
    { "name": "UNKNOWN_SERVER_ERROR", "value": -1,
      "about": "The server experienced an unexpected error when processing the 
request." },
    { "name": "NONE", "value": 0,
      "about": "No error." },
    { "name": "OFFSET_OUT_OF_RANGE", "value": 1,
      "about": "The requested offset is not within the range of offsets 
maintained by the server." },
  ...
  ]
}
{code}

 * The `valueType` is the type of the integer values.
 * The `codes` lists each of the allowed values. The `about` is optional.

This would generate a class of constants:

{code:language=java}
class ErrorCodes {
    public final static short UNKNOWN_SERVER_ERROR = -1;
    public final static short NONE = 0;
    ...

    public static boolean isValid(short v) {
        return NONE <= v && v <= MAX; 
    }
}
{code}

* The {{isValid()}} method validates that its parameter is one of the allowed 
values.
* It's an error for two constants to have the same value.
* There need be no requirement for the values to be contiguous.


Continuing the example this allows the existing `Errors` enum to be written as:

{code:language=java}
enum Errors {
    NONE(ErrorCodes.NONE, ...);
    ...
}
{code}

h2. Using codes in field specs

The field spec will support a {{domain}} property which names the set of codes 
that values of the field may take. For example an {{ErrorCode}} field:

{code:language=js}
 {
  "name": "ErrorCode",
  "type": "int16",
  "domain": {
    "name": "ErrorCodes",
    "values": [
      { "name": "NONE", "validVersions": "0+" },
      { "name": "FOO", "validVersions": "0+" },
      { "name": "BAR", "validVersions": "3+" },
      ...
    ]
   }
 }
{code}

* The {{name}} is the name of a corresponding codes declaration.
* The {{values}} is optional. When it's missing then any of the values in the 
codes declaration are permitted. When it's present, then only the given values 
are allowed. Values are given as an object with a `name` that identifies a 
value from the codes declaration and optionally, a {validVersions} which allows 
a given code to only be allowed in the given versions of the message.

The owning {Data} class (or inner classes of the {Data} class) will gain a 
method for validating the error codes. The implementation would depend on 
whether {values} and/or {validVersions} were given, but might look like this:

{code:language=java}
public static boolean isValidErrorCode(short v, short version) {
    switch (version) {
    case 0:
    case 1:
    case 2:
        return v == ErrorCodes.NONE || v == ErrorCodes.FOO;
    case 3:
        return v == ErrorCodes.NONE || v == ErrorCodes.FOO || v == 
ErrorCodes.BAR;
     }
}
{code}

h2. Validation

We can call the validation methods and throw:

 * When serializing requests
 * When deserializing requests
 * When serializing responses, except for error code fields.

The reason for distinguishing error code fields arises from the difficultly of 
knowing for certain which exception types can be thrown in the code called from 
the handler in the broker. We don't want a mistake the allowed error codes to 
result in a needless exception in the broker. So for these instead of throwing 
we could log the unexpected value.

We could use properties of the field spec to configure what code was generated 
for serialization and deserialization on a per-message basis.

Thoughts?



> Add error specifications to KAFKA-7609
> --------------------------------------
>
>                 Key: KAFKA-7787
>                 URL: https://issues.apache.org/jira/browse/KAFKA-7787
>             Project: Kafka
>          Issue Type: Sub-task
>            Reporter: Colin McCabe
>            Assignee: Tom Bentley
>            Priority: Minor
>
> In our RPC JSON, it would be nice if we could specify what versions of a 
> response could contain what errors.  See the discussion here: 
> https://github.com/apache/kafka/pull/5893#discussion_r244841051



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to