-
-
Notifications
You must be signed in to change notification settings - Fork 11
Description
After thinking thoroughly about extensions and protocolInfo objects and their schemas, this is the proposal I have.
Context
AsyncAPI (and also OpenAPI) allows you to annotate your document with properties starting by x- and whose values can be anything. We now want to provide a catalog of extensions but we MUST not break this "freedom".
In version 2, we introduced "protocol info" objects. They are also treated as extensions but, unlike the other ones, they can only live inside the protocolInfo object. They consist of a key (e.g., kafka) and a value of type object. The value will contain protocol-specific information.
Problem
We'll want to iterate on extensions independently, i.e., without having to release a new AsyncAPI specification version. Therefore, when using an extension inside an AsyncAPI document, we should have the possibility to specify the version of the extension we're using.
As an example, if we have the following definition:
asyncapi: '2.0.0'
channels:
/tweets:
subscribe:
protocolInfo:
kafka:
clientId: 'my-client-id'We're saying that, when using Kafka, we want the code to subscribe using my-client-id as the Client Id. This kafka protocolInfo object is validated using the following (simplified) schema:
{
"type": "object",
"properties": {
"clientId": {
"type": "string"
}
}
}However, after some time, our extension is growing a lot and we want to reorganize the fields in the kafka object as follows:
...
protocolInfo:
kafka:
client:
id: 'my-client-id'And the new schema is the following:
{
"type": "object",
"properties": {
"client": {
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
}
}
}This is a breaking change so, suddenly, we would be breaking the workflow for these people using the Kafka protocolInfo extension. This is an undesirable side-effect we can avoid by specifying a version string in the extension:
asyncapi: '2.0.0'
channels:
/tweets:
subscribe:
protocolInfo:
kafka:
_v: '0.1.0'
clientId: 'my-client-id'Note this version is the version of the extension, not the Kafka version.
It seems clear we need a version strategy, however, while this is fine for protocolInfo extensions, it might not be the case for specification extensions, because they may not be of type "object". Consider the following example:
asyncapi: '2.0.0'
info:
x-twitter: @PermittedSocIn this case, we can't add the version (_v: 'x.x.x'). Even more, specification extensions do not have to follow our formatting. Remember they are free-form values and they may not be in our catalog or people just don't want to validate them at all.
Solution
For specification extensions, we assume the following:
- If the extension is not in our catalog (or provided in another way), we MUST NOT perform validation on the extension.
- If version (
_v) is omitted and the extension is in our catalog, we MUST perform validation against the "latest" version of the extension. - If version (
_v) is omitted and the tooling provides the definition, we MUST perform validation against the provided extension definition. - If version (
_v) is provided and the extension is in our catalog, we MUST perform validation against the provided version of the extension. - If version (
_v) is provided and the tooling provides the definition for another version, we MUST NOT perform validation on the extension.
For protocolInfo extensions, we assume the following:
- Version (
_v) is mandatory. - If the protocolInfo extension is in our catalog (or provided in another way), we MUST perform validation against the provided version of the extension.
- If the protocolInfo extension is not in our catalog and it's not provided in another way, we MUST NOT perform validation on the protocolInfo extension.
- If the tooling provides the definition for another version, we MUST NOT perform validation on the protocolInfo extension.
Open questions
- Should we call the version field
_v? Another options:_version,version,extension_version,_extension_version. Please, take into account that protocolInfo extensions may have to use theversionfield for the protocol version. I personally prefer the_vname because 1) it starts with an underscore and makes it look like something special or "meta"; and 2) it's short and not similar toversion. - Should we enforce semantic versioning?
- Should we accept version ranges in the
_vfield? E.g.,1.3.x,1.x,*,latest, etc.