From 4597e1074fe6a4e89fe362fe5a42dfe8ad1d4a5c Mon Sep 17 00:00:00 2001 From: akshatnema Date: Fri, 28 Jun 2024 13:29:25 +0000 Subject: [PATCH] docs(extension): update latest bindings docs --- config/edit-page-config.json | 4 + markdown/docs/reference/bindings/_section.md | 4 + markdown/docs/reference/bindings/amqp.md | 159 +++++++++ markdown/docs/reference/bindings/amqp1.md | 42 +++ .../docs/reference/bindings/anypointmq.md | 244 +++++++++++++ .../docs/reference/bindings/googlepubsub.md | 179 ++++++++++ markdown/docs/reference/bindings/http.md | 103 ++++++ markdown/docs/reference/bindings/ibmmq.md | 328 ++++++++++++++++++ markdown/docs/reference/bindings/jms.md | 165 +++++++++ markdown/docs/reference/bindings/kafka.md | 207 +++++++++++ markdown/docs/reference/bindings/mercure.md | 48 +++ markdown/docs/reference/bindings/mqtt.md | 189 ++++++++++ markdown/docs/reference/bindings/mqtt5.md | 79 +++++ markdown/docs/reference/bindings/nats.md | 38 ++ markdown/docs/reference/bindings/pulsar.md | 91 +++++ markdown/docs/reference/bindings/redis.md | 45 +++ markdown/docs/reference/bindings/scripts.md | 6 + markdown/docs/reference/bindings/sns.md | 305 ++++++++++++++++ markdown/docs/reference/bindings/solace.md | 207 +++++++++++ markdown/docs/reference/bindings/sqs.md | 247 +++++++++++++ markdown/docs/reference/bindings/stomp.md | 45 +++ .../docs/reference/bindings/websockets.md | 58 ++++ public/img/docs/SNS-HTTP.png | Bin 0 -> 50765 bytes public/img/docs/SNS-SQS-Pub-Sub.png | Bin 0 -> 47278 bytes public/img/docs/SQS-Point-To-Point.png | Bin 0 -> 37204 bytes 25 files changed, 2793 insertions(+) create mode 100644 markdown/docs/reference/bindings/_section.md create mode 100644 markdown/docs/reference/bindings/amqp.md create mode 100644 markdown/docs/reference/bindings/amqp1.md create mode 100644 markdown/docs/reference/bindings/anypointmq.md create mode 100644 markdown/docs/reference/bindings/googlepubsub.md create mode 100644 markdown/docs/reference/bindings/http.md create mode 100644 markdown/docs/reference/bindings/ibmmq.md create mode 100644 markdown/docs/reference/bindings/jms.md create mode 100644 markdown/docs/reference/bindings/kafka.md create mode 100644 markdown/docs/reference/bindings/mercure.md create mode 100644 markdown/docs/reference/bindings/mqtt.md create mode 100644 markdown/docs/reference/bindings/mqtt5.md create mode 100644 markdown/docs/reference/bindings/nats.md create mode 100644 markdown/docs/reference/bindings/pulsar.md create mode 100644 markdown/docs/reference/bindings/redis.md create mode 100644 markdown/docs/reference/bindings/scripts.md create mode 100644 markdown/docs/reference/bindings/sns.md create mode 100644 markdown/docs/reference/bindings/solace.md create mode 100644 markdown/docs/reference/bindings/sqs.md create mode 100644 markdown/docs/reference/bindings/stomp.md create mode 100644 markdown/docs/reference/bindings/websockets.md create mode 100644 public/img/docs/SNS-HTTP.png create mode 100644 public/img/docs/SNS-SQS-Pub-Sub.png create mode 100644 public/img/docs/SQS-Point-To-Point.png diff --git a/config/edit-page-config.json b/config/edit-page-config.json index dbd5fa50b9eb..d60276823f1a 100644 --- a/config/edit-page-config.json +++ b/config/edit-page-config.json @@ -1,4 +1,8 @@ [ + { + "value": "reference/bindings/", + "href": "https://github.com/asyncapi/bindings/tree/master" + }, { "value": "/tools/generator", "href": "https://github.com/asyncapi/generator/tree/master/docs" diff --git a/markdown/docs/reference/bindings/_section.md b/markdown/docs/reference/bindings/_section.md new file mode 100644 index 000000000000..d2405cd9f71a --- /dev/null +++ b/markdown/docs/reference/bindings/_section.md @@ -0,0 +1,4 @@ +--- +title: Bindings +weight: 11 +--- \ No newline at end of file diff --git a/markdown/docs/reference/bindings/amqp.md b/markdown/docs/reference/bindings/amqp.md new file mode 100644 index 000000000000..c6357f14942c --- /dev/null +++ b/markdown/docs/reference/bindings/amqp.md @@ -0,0 +1,159 @@ +--- +title: 'amqp' +weight: 11 +--- + +# AMQP 0-9-1 Bindings + +This document defines how to describe AMQP-specific information on AsyncAPI. + + + +## Version + +Current version is `0.3.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Channel Binding Object + +This object contains information about the channel representation in AMQP. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`is` | string | Defines what type of channel is it. Can be either `queue` or `routingKey` (default). +`exchange` | Map[string, any] | When `is`=`routingKey`, this object defines the exchange properties. +`exchange.name` | string | The name of the exchange. It MUST NOT exceed 255 characters long. +`exchange.type` | string | The type of the exchange. Can be either `topic`, `direct`, `fanout`, `default` or `headers`. +`exchange.durable` | boolean | Whether the exchange should survive broker restarts or not. +`exchange.autoDelete` | boolean | Whether the exchange should be deleted when the last queue is unbound from it. +`exchange.vhost` | string | The virtual host of the exchange. Defaults to `/`. +`queue` | Map[string, any] | When `is`=`queue`, this object defines the queue properties. +`queue.name` | string | The name of the queue. It MUST NOT exceed 255 characters long. +`queue.durable` | boolean | Whether the queue should survive broker restarts or not. +`queue.exclusive` | boolean | Whether the queue should be used only by one connection or not. +`queue.autoDelete` | boolean | Whether the queue should be deleted when the last consumer unsubscribes. +`queue.vhost` | string | The virtual host of the queue. Defaults to `/`. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +channels: + userSignup: + address: 'user/signup' + bindings: + amqp: + is: routingKey + exchange: + name: myExchange + type: topic + durable: true + autoDelete: false + vhost: / + bindingVersion: 0.3.0 +``` + +```yaml +channels: + userSignup: + address: 'user/signup' + bindings: + amqp: + is: queue + queue: + name: my-queue-name + durable: true + exclusive: true + autoDelete: false + vhost: / + bindingVersion: 0.3.0 +``` + + + +## Operation Binding Object + +This object contains information about the operation representation in AMQP. + +##### Fixed Fields + +Field Name | Type | Applies To Action | Description +---|:---:|:---:|--- +`expiration` | integer | `receive`, `send` | TTL (Time-To-Live) for the message. It MUST be greater than or equal to zero. +`userId` | string | `receive`, `send` | Identifies the user who has sent the message. +`cc` | [string] | `receive`, `send` | The routing keys the message should be routed to at the time of publishing. +`priority` | integer | `receive`, `send` | A priority for the message. +`deliveryMode` | integer | `receive`, `send` | Delivery mode of the message. Its value MUST be either 1 (transient) or 2 (persistent). +`mandatory` | boolean | `receive` | Whether the message is mandatory or not. +`bcc` | [string] | `receive` | Like [cc](#operationBindingObjectCC) but consumers will not receive this information. +`timestamp` | boolean | `receive`, `send` | Whether the message should include a timestamp or not. +`ack` | boolean | Subscribe | Whether the consumer should ack the message or not. +`bindingVersion` | string | `receive`, `send` | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +operations: + userSignup: + channel: + $ref: '#/channels/userSignup' + bindings: + amqp: + expiration: 100000 + userId: guest + cc: ['user.logs'] + priority: 10 + deliveryMode: 2 + mandatory: false + bcc: ['external.audit'] + timestamp: true + ack: false + bindingVersion: 0.3.0 +``` + + + + +## Message Binding Object + +This object contains information about the message representation in AMQP. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`contentEncoding` | string | A MIME encoding for the message content. +`messageType` | string | Application-specific message type. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +```yaml +channels: + userSignup: + address: 'user/signup' + messages: + userSignupMessage: + bindings: + amqp: + contentEncoding: gzip + messageType: 'user.signup' + bindingVersion: 0.3.0 +``` diff --git a/markdown/docs/reference/bindings/amqp1.md b/markdown/docs/reference/bindings/amqp1.md new file mode 100644 index 000000000000..1fb456b3f9ab --- /dev/null +++ b/markdown/docs/reference/bindings/amqp1.md @@ -0,0 +1,42 @@ +--- +title: 'amqp1' +weight: 12 +--- + +# AMQP 1.0 Bindings + +This document defines how to describe AMQP 1.0-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/anypointmq.md b/markdown/docs/reference/bindings/anypointmq.md new file mode 100644 index 000000000000..2c8d3efa40a1 --- /dev/null +++ b/markdown/docs/reference/bindings/anypointmq.md @@ -0,0 +1,244 @@ +--- +title: 'anypointmq' +weight: 13 +--- + +# Anypoint MQ Bindings + +This document defines how to describe Anypoint MQ-specific information in AsyncAPI documents. + +[Anypoint MQ](https://docs.mulesoft.com/mq/) is MuleSoft's multi-tenant, cloud messaging service and is fully integrated with [Anypoint Platform](https://www.mulesoft.com/platform/enterprise-integration). + + +## Versions + +The version of this bindings specification is `0.1.0`. +This is also the `bindingVersion` for all binding objects defined by this specification. +In any given binding object, `latest` MAY alternatively be used to refer to the currently latest published version of this bindings specification. + +## Terminology + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt). + +## Protocol + +These bindings use the `anypointmq` [protocol](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#definitionsProtocol) in AsyncAPI documents to denote connections to and interactions with Anypoint MQ message brokers. + +The Anypoint MQ protocol is based on invocations of the [Anypoint MQ Broker REST API](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/). + +## Server Object + +The fields of the standard [Server Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#serverObject) are constrained and interpreted as follows: + +Server Object Field Name | Values for Anypoint MQ Protocol | Description +---|:---|:--- +`protocol` | `anypointmq` | **REQUIRED**. MUST be `anypointmq` for the scope of this specification. +`host` | e.g., `https://mq-us-east-1.anypoint.mulesoft.com` | **REQUIRED**. MUST be the endpoint HOST part of the URL of the Anypoint MQ Broker REST API. Valid examples are `https://mq-us-east-1.anypoint.mulesoft.com` and `https://mq-eu-central-1.eu1.anypoint.mulesoft.com` (and _not_ `https://mq-us-east-1.anypoint.mulesoft.com/api`, or `https://.../api/v1`). +`pathname` | e.g., `/api` | **REQUIRED**. MUST be the endpoint path part of the URL of the Anypoint MQ Broker REST API _excluding_ the final major version indicator (e.g., `v1`). Valid examples are `/api` and (and _not_ `https://.../api/v1`). +`protocolVersion` | e.g., `v1` | **OPTIONAL**, defaults to `v1`. If present MUST be the major version indicator of the Anypoint MQ Broker REST API omitted from the `url`, e.g. `v1`. +`security` | suitably configured OAuth 2.0 client credentials grant type | **REQUIRED**. Authentication against the MuleSoft-hosted Anypoint MQ message brokers uses the OAuth 2.0 client credentials grant type. At runtime, the client ID and client secret values of an Anypoint MQ client app must be supplied. Also, the OAuth 2.0 scopes are currently not client-configurable. The `security` field of the server object MUST correctly match these constraints. + +Note that the choice of a particular Anypoint MQ client app (via its client ID and secret) decides the Anypoint Platform organization ID and environment (ID) to be those in which this client app is defined. See the [Anypoint MQ documentation](https://docs.mulesoft.com/mq/mq-client-apps) for details on how to configure Anypoint MQ client apps. + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + +## Channel Binding Object + +The Anypoint MQ [Channel Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#channel-bindings-object) is defined by a [JSON Schema](json_schemas/channel.json), which defines these fields: + +Field Name | Type | Description +---|:---:|--- +`destination` | string | **OPTIONAL**, defaults to the channel name. The destination (queue or exchange) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name in Anypoint MQ. +`destinationType` | string | **OPTIONAL**, defaults to `queue`. The type of destination, which MUST be either `exchange` or `queue` or `fifo-queue`. SHOULD be specified to document the messaging model (publish/subscribe, point-to-point, strict message ordering) supported by this channel. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +Note that an Anypoint MQ exchange can only be sent to, not received from. To receive messages sent to an exchange, [an intermediary queue must be defined and bound to the exchange](https://docs.mulesoft.com/mq/mq-understanding#message-exchanges). In this bindings specification, these intermediary queues are not exposed in the AsyncAPI document. Instead, it is simply assumed that whenever messages must be received from an exchange, such an intermediary queue is involved yet invisible in the AsyncAPI document. + +### Examples + +The following example shows two channels where does not apply any bindings and the second one applying `anyointmq` bindings. + +```yaml +channels: + userSignup: + address: 'user/signup' + description: | + This application receives command messages from this channel about users to sign up. + Minimal configuration, omitting a channel binding object. + messages: + #... + + userSignup: + address: 'user/signup' + description: | + This application sends events to this channel about users that have signed up. + Explicitly provides a channel binding object. + messages: + #... + bindings: + anypointmq: + destination: user-signup-exchg + destinationType: exchange + bindingVersion: '0.1.0' +``` + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + +## Message Binding Object + +The Anypoint MQ [Message Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#message-bindings-object) defines these fields: + +Field Name | Type | Description +---|:---:|--- +`headers` | [Schema Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject) \| [Reference Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject) | **OPTIONAL**. A Schema object containing the definitions for Anypoint MQ-specific headers (so-called protocol headers). This schema MUST be of type `object` and have a `properties` key. Examples of Anypoint MQ protocol headers are `messageId` and `messageGroupId`. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +Note that application headers must be specified in the [`headers` field of the standard Message Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#messageObjectHeaders) and are transmitted in the [`properties` section of the Anypoint MQ message](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/). +In contrast, protocol headers such as `messageId` must be specified in the [`headers` field of the message binding object](#messageBindingObjectHeaders) and are transmitted in the [`headers` section of the Anypoint MQ message](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/). + +### Examples + +The following example shows a `channels` object with two channels, each having one operation (`subscribe` or `publish`) with one message. Only the message of the `subscribe` operation has a message binding object for `anypointmq`: + +```yaml +channels: + userSignup: + address: 'user/signup' + messages: + #... + userSignup: + address: 'user/signup' + messages: + userSignupMessage: + headers: + type: object + properties: + correlationId: + description: Correlation ID set by application + type: string + payload: + type: object + properties: + #... + correlationId: + description: Correlation ID is specified as a header and transmitted in the Anypoint MQ message properties section + location: $message.header#/correlationId + bindings: + anypointmq: + headers: + type: object + properties: + messageId: + type: string + bindingVersion: '0.1.0' +``` + +## Complete Example + +The following is a complete, simple AsyncAPI document illustrating the usage of all binding objects defined in this bindings specification, with all their fields. + +```yaml +asyncapi: 3.0.0 +info: + title: Example with Anypoint MQ + version: 0.0.1 +servers: + development: + host: mq-us-east-1.anypoint.mulesoft.com + pathname: /api + protocol: anypointmq + protocolVersion: v1 + description: > + Anypoint MQ broker for development, in the US East (N. Virginia) runtime + plane + + under management of the US control plane. + security: + - $ref: '#/components/securitySchemes/oauthDev' + production: + host: mq-eu-central-1.eu1.anypoint.mulesoft.com + pathname: /api + protocol: anypointmq + protocolVersion: v1 + description: > + Anypoint MQ broker for production, in the EU Central (Frankfurt) runtime + plane + + under management of the EU control plane. + security: + - $ref: '#/components/securitySchemes/oauthProd' + bindings: + anypointmq: + bindingVersion: 0.1.0 +channels: + user/signup: + address: user/signup + messages: + signUpUser.message: + contentType: application/json + headers: + type: object + properties: + correlationId: + description: Correlation ID set by application + type: string + payload: + type: object + properties: + username: + type: string + minLength: 3 + correlationId: + description: >- + Correlation ID is specified as a header and transmitted in the + Anypoint MQ message properties section + location: $message.header#/correlationId + bindings: + anypointmq: + headers: + type: object + properties: + messageId: + type: string + bindingVersion: 0.1.0 + description: > + This application receives command messages from this channel about users + to sign up. + bindings: + anypointmq: + destination: user-signup-queue + destinationType: fifo-queue + bindingVersion: 0.1.0 +operations: + signUpUser: + action: receive + channel: + $ref: '#/channels/user~1signup' + description: > + This application receives command messages via this operation about users + to sign up. + messages: + - $ref: '#/channels/user~1signup/messages/signUpUser.message' +components: + securitySchemes: + oauthDev: + type: oauth2 + flows: + clientCredentials: + tokenUrl: 'https://mq-us-east-1.anypoint.mulesoft.com/api/v1/authorize' + scopes: {} + oauthProd: + type: oauth2 + flows: + clientCredentials: + tokenUrl: 'https://mq-eu-central-1.eu1.anypoint.mulesoft.com/api/v1/authorize' + scopes: {} +``` diff --git a/markdown/docs/reference/bindings/googlepubsub.md b/markdown/docs/reference/bindings/googlepubsub.md new file mode 100644 index 000000000000..c40d92e9a0ba --- /dev/null +++ b/markdown/docs/reference/bindings/googlepubsub.md @@ -0,0 +1,179 @@ +--- +title: 'googlepubsub' +weight: 14 +--- + +# Google Cloud Pub/Sub Bindings + +This document defines how to describe Google Cloud Pub/Sub specific information with AsyncAPI. + + + +## Version + +Current version is `0.2.0`. + + + +## Channel Binding Object + +The `Channel Bindings Object` is used to describe the Google Cloud Pub/Sub specific +[Topic](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create) details with AsyncAPI. + +Field Name | Type | Description +---|---|--- +`bindingVersion`|String|The current version is `0.2.0` +`labels`|Object|An object of key-value pairs _(These are used to categorize Cloud Resources like Cloud Pub/Sub Topics.)_ +`messageRetentionDuration`|String|Indicates the minimum duration to retain a message after it is published to the topic _(Must be a valid [Duration](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Duration).)_ +`messageStoragePolicy`|[Message Storage Policy Object](#message-storage-policy-object)|Policy constraining the set of Google Cloud Platform regions where messages published to the topic may be stored +`schemaSettings`|[Schema Settings Object](#schema-settings-object)|Settings for validating messages published against a schema + + + +### Message Storage Policy Object + +The `Message Storage Policy Object` is used to describe the Google Cloud Pub/Sub +[MessageStoragePolicy](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#MessageStoragePolicy) +Object with AsyncAPI. + +Field Name | Type | Description +---|---|--- +`allowedPersistenceRegions`|String[]|A list of IDs of GCP regions where messages that are published to the topic may be persisted in storage + + + +### Schema Settings Object + +The `Schema Settings Object` is used to describe the Google Cloud Pub/Sub +[SchemaSettings](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#SchemaSettings) Object with +AsyncAPI. + +Field Name | Type | Description +---|---|--- +`encoding`|String|The encoding of the message _(Must be one of the possible [Encoding](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#encoding) values.)_ +`firstRevisionId`|String|The minimum _(inclusive)_ revision allowed for validating messages +`lastRevisionId`|String|The maximum _(inclusive)_ revision allowed for validating messages +`name`|String|The name of the schema that messages published should be validated against _(The format is `projects/{project}/schemas/{schema}`.)_ + + + +### Example + +```yaml +# ... +channels: + topic-avro-schema: + address: projects/your-project/topics/topic-avro-schema + bindings: + googlepubsub: + schemaSettings: + encoding: json + name: projects/your-project/schemas/message-avro +# ... + topic-proto-schema: + address: projects/your-project/topics/topic-proto-schema + bindings: + googlepubsub: + messageRetentionDuration: 86400s + messageStoragePolicy: + allowedPersistenceRegions: + - us-central1 + - us-central2 + - us-east1 + - us-east4 + - us-east5 + - us-east7 + - us-south1 + - us-west1 + - us-west2 + - us-west3 + - us-west4 + schemaSettings: + encoding: binary + name: projects/your-project/schemas/message-proto +# ... +``` + + + +## Message Binding Object + +The `Message Binding Object` is used to describe the Google Cloud Pub/Sub specific +[PubsubMessage](https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage) details, alongside with pertintent +parts of the Google Cloud Pub/Sub +[Schema](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.schemas#Schema) +Object, with AsyncAPI. + +Field Name | Type | Description +---|---|--- +`bindingVersion`|String|The current version is `0.2.0` +`attributes`|Object|Attributes for this message _(If this field is empty, the message must contain non-empty data. This can be used to filter messages on the subscription.)_ +`orderingKey`|String|If non-empty, identifies related messages for which publish order should be respected _(For more information, see [ordering messages](https://cloud.google.com/pubsub/docs/ordering).)_ +`schema`|[Schema Definition Object](#schema-definition-object)|Describes the schema used to validate the payload of this message + + + +### Schema Definition Object + +The `Schema Definition Object` is used to describe the Google Cloud Pub/Sub +[Schema]([Schema](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.schemas#Schema)) Object with AsyncAPI. +While some of this information could be, or is, described using native AsyncAPI, for consistency it makes sense to +provide this information here at all times, especially for cases where AsyncAPI does not natively support describing +payloads using a supported Google Cloud Pub/Sub schema format like Protobuf. + +Field Name | Type | Description +---|---|--- +`name`|String|The name of the schema + + + +### Example + +```yaml +# ... +components: + messages: + messageAvro: + bindings: + googlepubsub: + schema: + name: projects/your-project/schemas/message-avro + contentType: application/json + name: MessageAvro + payload: + schema: + fields: + - name: message + type: string + name: Message + type: record + schemaFormat: application/vnd.apache.avro+yaml;version=1.9.0 + messageProto: + bindings: + googlepubsub: + schema: + name: projects/your-project/schemas/message-proto + contentType: application/octet-stream + name: MessageProto + payload: + schema: | + syntax = "proto3"; + + message Message { + required string message = 1; + } + schemaFormat: application/vnd.google.protobuf;version=3 +# ... +``` + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/http.md b/markdown/docs/reference/bindings/http.md new file mode 100644 index 000000000000..bf275a01f497 --- /dev/null +++ b/markdown/docs/reference/bindings/http.md @@ -0,0 +1,103 @@ +--- +title: 'http' +weight: 15 +--- + +# HTTP Bindings + +This document defines how to describe HTTP-specific information on AsyncAPI. + + + +## Version + +Current version is `0.3.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`method` | string | The HTTP method for the request. Its value MUST be one of `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`, `CONNECT`, and `TRACE`. +`query` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for each query parameter. This schema MUST be of type `object` and have a `properties` key. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +channels: + employees: + address: /employees +operations: + employees: + action: send + bindings: + http: + method: GET + query: + type: object + required: + - companyId + properties: + companyId: + type: number + minimum: 1 + description: The Id of the company. + additionalProperties: false + bindingVersion: '0.3.0' +``` + + + +## Message Binding Object + +This object contains information about the message representation in HTTP. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`headers` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for HTTP-specific headers. This schema MUST be of type `object` and have a `properties` key. +`statusCode` | number | The HTTP response status code according to [RFC 9110](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes). `statusCode` is only relevant for messages referenced by the [Operation Reply Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#operationReplyObject), as it defines the status code for the response. In all other cases, this value can be safely ignored. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +```yaml +channels: + test: + address: /test + messages: + testMessage: + bindings: + http: + statusCode: 200 + headers: + type: object + properties: + Content-Type: + type: string + enum: ['application/json'] + bindingVersion: '0.3.0' +``` + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject diff --git a/markdown/docs/reference/bindings/ibmmq.md b/markdown/docs/reference/bindings/ibmmq.md new file mode 100644 index 000000000000..5b671e334580 --- /dev/null +++ b/markdown/docs/reference/bindings/ibmmq.md @@ -0,0 +1,328 @@ +--- +title: 'ibmmq' +weight: 16 +--- + +# IBM MQ Bindings + +This document defines how to describe IBM MQ specific information with AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + +## Terminology + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt). + +## AsyncAPI considerations + +This specification binding requests that the AsyncAPI specification reserve the IBM MQ protocol to allow connections to queue manager endpoints to be defined within the server object. + +AsyncAPI Object Fixed Field Name | Reserved Value for IBM MQ Protocol | Description +---|:---|:--- +`server.protocol` | ibmmq | IBM MQ protocol. +`server.protocol` | ibmmq-secure | IBM MQ protocol over TLS. + +## URI scheme considerations + +For the purposes of establishing an IBM MQ binding for use within AsyncAPI, this document defines the URI scheme `ibmmq://` consisting of components and generic URI syntax as specified in [RFC3986](https://tools.ietf.org/html/rfc3986) + +### Defining an IBM MQ queue manager endpoint in the server object `url` field + +When defining an IBM MQ `url` for a queue manager endpoint, the `ibmmq://` URI scheme MUST be used. IBM MQ URIs are defined using the following components. + +URI Component | IBM MQ reference | Applicability | Description | +---|:---|:--|:-- +`scheme` | `ibmmq://` | REQUIRED | The URI scheme used to represent an IBM MQ endpoint. +`authority` | `:port` | REQUIRED | The network IP address or hostname and port of the queue manager endpoint. | +`path` | `queueManager` | OPTIONAL | The queue manager name. If no queue manager name is specified this segment is left undefined, for example `ibmmq://hostname:{port}//CHANNEL.NAME` +`path` | `mqChannelName` | REQUIRED | The `SVRCONN` channel to use for communication with an IBM MQ queue manager. When connecting to a queue manager, IBM MQ partitions this communication into logical channels. + +URI `query` or `fragment` components MUST NOT be used within the `ibmmq://` scheme. Path components that contain characters reserved by RFC2936 such as `/` MUST be percent encoded as defined in [Section 2.2 of RFC2936](https://tools.ietf.org/html/rfc3986#section-2.2). `port` MUST be specified as part of the authority component in the `ibmmq://` scheme. + + +### Defining IBM MQ queue manager endpoints with the AsyncAPI Server Object + +This section defines the convention for how IBM MQ queue manager endpoints are encoded within the AsyncAPI Server Object fields. A `groupId` field has been made available on the IBM MQ AsyncAPI server binding object to allow server objects to be defined as a related collection. This is necessary to group, or cluster, IBM MQ queue manager endpoints within the AsyncAPI specification and where a Client Channel Definition Table ([CCDT](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.con.doc/q132905_.html)) reference is not appropriate. + + +##### Example of two possible MQ servers defined using ibmmq url syntax +```yaml +servers: + production1: + url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN + protocol: ibmmq + production2: + url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN + protocol: ibmmq +``` + +##### Example of single MQ server defined using ibmmq url syntax and with no queue manager name specified +```yaml +servers: + production: + url: ibmmq://qmgr1host:1414//DEV.APP.SVRCONN + protocol: ibmmq +``` + +## Defining an IBM MQ queue manager endpoint CCDT in the `url` field +When defining a connection to IBM MQ, a CCDT connection file can be specified. The server url will specify the location of the file with additional information contained within the server binding to specify its usage. + +##### Example using an IBM MQ CCDT file url + +```yaml +servers: + production1: + url: 'http://my-ccdt-json-file' + protocol: ibmmq + production2: + url: 'file://myccdt.json' + protocol: ibmmq +``` + + + +## Server Binding Object + +This object contains server connection information about the IBM MQ server, referred to as an IBM MQ queue manager. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification. + +##### Fixed Fields + + +Field Name | Type | Description | Applicability \[default\] | Constraints +---|:---:|---|:---|:--- +`groupId` | string | Defines a logical group of IBM MQ server objects. This is necessary to specify multi-endpoint configurations used in high availability deployments. If omitted, the server object is not part of a group. | OPTIONAL | MUST NOT be specified for URI Scheme `http://` or `file://` +`ccdtQueueManagerName` | string | The name of the IBM MQ queue manager to bind to in the CCDT file. | OPTIONAL [`*`] | MUST NOT be specified for URI Scheme `ibmmq://` +`cipherSpec` | string | The recommended cipher specification used to establish a TLS connection between the client and the IBM MQ queue manager. More information on SSL/TLS cipher specifications supported by IBM MQ can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.dev.doc/q113220_.html) in the IBM MQ Knowledge Center. | OPTIONAL [`ANY`] | MUST NOT be specified for protocol `ibmmq` or URI Scheme `file://` or `http://` +`multiEndpointServer` | boolean | If `multiEndpointServer` is `true` then multiple connections can be workload balanced and applications should not make assumptions as to where messages are processed. Where message ordering, or affinity to specific message resources is necessary, a single endpoint (`multiEndpointServer` = `false`) may be required. | OPTIONAL [`false`] | MUST NOT be specified for URI Scheme `file://` or `http://` +`heartBeatInterval` | integer | The recommended value (in seconds) for the heartbeat sent to the queue manager during periods of inactivity. A value of zero means that no heart beats are sent. A value of `1` means that the client will use the value defined by the queue manager. More information on heart beat interval can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q108450_.html) in the IBM MQ Knowledge Center. | OPTIONAL [`300`] | MUST be `0-999999` +`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | - + +This object MUST contain only the properties defined above. + +##### Example for multiple endpoints defined in the AsyncAPI configuration + +```yaml +servers: + production1: + url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Production Instance 1 + bindings: + ibmmq: + groupId: PRODCLSTR1 + cipherSpec: ANY_TLS12_OR_HIGHER + bindingVersion: 0.1.0 + production2: + url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Production Instance 2 + bindings: + ibmmq: + groupId: PRODCLSTR1 + bindingVersion: 0.1.0 +``` + +##### Example using combined strategy + +```yaml +servers: + production: + url: 'http://my-ccdt-json-file' + protocol: ibmmq-secure + description: Production MQ Instance + bindings: + ibmmq: + ccdtQueueManagerName: qm1 + test: + url: ibmmq://qmgrtest:1414/qm2/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Test MQ Instance + bindings: + ibmmq: + cipherSpec: ANY_TLS12_OR_HIGHER + bindingVersion: 0.1.0 +``` + + + + + +## Channel Binding Object + +This object contains information about the channel representation in IBM MQ. Each channel corresponds to a Queue or Topic within IBM MQ. + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:---:|---|:---|:--- +`destinationType` | string | Defines the type of AsyncAPI channel. | OPTIONAL [`topic`] | MUST be either `topic` or `queue`. For type `topic`, the AsyncAPI channel name MUST be assumed for the IBM MQ topic string unless overridden. +`queue` | Map[string, any] | Defines the properties of a queue. | REQUIRED if `destinationType` = `queue` | `queue` and `topic` fields MUST NOT coexist within a channel binding +`queue.`
`objectName`
| string | Defines the name of the IBM MQ queue associated with the channel. | REQUIRED | A value MUST be specified. MUST NOT exceed 48 characters in length. MUST be a valid IBM MQ queue name +`queue.`
`isPartitioned`
| boolean | Defines if the queue is a cluster queue and therefore partitioned. If `true`, a binding option MAY be specified when accessing the queue. More information on binding options can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q101870_.html#q101870___BIND_ON_OPEN) in the IBM MQ Knowledge Center. | OPTIONAL [`false`] | If `false`, binding options SHOULD NOT be specified when accessing the queue. +`queue.`
`exclusive`
| boolean | Specifies if it is recommended to open the queue exclusively. | OPTIONAL [`false`] | - +`topic` | Map[string, any] | Defines the properties of a topic. | OPTIONAL if `destinationType` = `topic` | `queue` and `topic` fields MUST NOT coexist within a channel binding. +`topic.`
`string`
| string | The value of the IBM MQ topic string to be used. | OPTIONAL *
Note: if specified, SHALL override AsyncAPI channel name.
* | MUST NOT exceed 10240 characters in length. MAY coexist with `topic.objectName` +`topic.`
`objectName`
| string | The name of the IBM MQ topic object. | OPTIONAL *
Note: if specified, SHALL override AsyncAPI channel name.
*| MUST NOT exceed 48 characters in length. MAY coexist with `topic.string` +`topic.`
`durablePermitted`
| boolean | Defines if the subscription may be durable. | OPTIONAL [`true`] | - +`topic.`
`lastMsgRetained`
| boolean | Defines if the last message published will be made available to new subscriptions. | OPTIONAL [`false`] | - +`maxMsgLength` | integer | The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered. More information on the maximum message length can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.adm.doc/q085520_.html#q085520___maxmsgl) in the IBM MQ Knowledge Center. | OPTIONAL [negotiated on IBM MQ channel]| MUST be `0-104,857,600` bytes (100 MB). +`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | - + + +This object MUST contain only the properties defined above. + +##### Example for an IBM MQ Topic where topic string is defined by AsyncAPI channel + +```yaml +channels: + user/signedup: +``` + +##### Example for AsyncAPI channel mapping to an IBM MQ topic with a specified MQ Topic object + +```yaml +channels: + user/signedup: + bindings: + ibmmq: + destinationType: topic + topic: + objectName: myTopicName + bindingVersion: 0.1.0 +``` + +##### Example for AsyncAPI channel mapping to an IBM MQ Queue + +```yaml +channels: + user/signedup: + bindings: + ibmmq: + destinationType: queue + queue: + objectName: myQueueName + exclusive: true + bindingVersion: 0.1.0 +``` + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Message Binding Object + +This object contains information about the message representation in IBM MQ. + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:---:|---|:---|:--- +`type` | string | The type of the message. | OPTIONAL [`string`] | MUST be either `string`, `jms` or `binary` +`headers` | string | Defines the IBM MQ message headers to include with this message. More than one header can be specified as a comma separated list. Supporting information on IBM MQ message formats can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q097520_.html) in the IBM MQ Knowledge Center. | OPTIONAL if `type` = `binary` | `headers` MUST NOT be specified if `type` = `string` or `jms` +`description` | string1 | Provides additional information for application developers: describes the message type or format. | OPTIONAL | - +`expiry` | integer | The recommended setting the client should use for the TTL (Time-To-Live) of the message. This is a period of time expressed in milliseconds and set by the application that puts the message. `expiry` values are API dependant e.g., MQI and JMS use different units of time and default values for *`unlimited`*. General information on IBM MQ message expiry can be found on this [page](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q097490_.html) in the IBM MQ Knowledge Center. | OPTIONAL [*`unlimited`*] | `expiry` value MUST be either `zero` (*`unlimited`*) or greater than zero. +`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | - + +This object MUST contain only the properties defined above. + +### Rich Text Formatting + +1 The `description` field of the IBM MQ message binding object MAY include CommonMark markdown formatting. A minimum markdown syntax as described by [CommonMark 0.27](https://spec.commonmark.org/0.27/) is assumed. + +##### Example for plain text message + +```yaml +channels: + user/signup: + publish: + message: + bindings: + ibmmq: + type: string + bindingVersion: 0.1.0 +``` + +##### Example for IBM MQ message using JMS + +```yaml +channels: + user/signup: + publish: + message: + bindings: + ibmmq: + type: jms + description: JMS stream message + bindingVersion: 0.1.0 +``` + +# AsyncAPI example with IBM MQ binding + +##### Example for AsyncAPI user signup + +```yaml +asyncapi: 2.0.0 +info: + title: Account Service + version: 1.0.0 + description: This service is in charge of processing user signups +servers: + production1: + url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Production Instance 1 + bindings: + ibmmq: + groupId: PRODCLSTR1 + cipherSpec: ANY_TLS12_OR_HIGHER + bindingVersion: 0.1.0 + production2: + url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Production Instance 2 + bindings: + ibmmq: + groupId: PRODCLSTR1 + cipherSpec: ANY_TLS12_OR_HIGHER + bindingVersion: 0.1.0 +channels: + user/signedup: + bindings: + ibmmq: + topic: + durablePermitted: true + bindingVersion: 0.1.0 + subscribe: + message: + $ref: '#/components/messages/UserSignedUp' + bindings: + ibmmq: + type: jms + description: JMS bytes message + bindingVersion: 0.1.0 +components: + messages: + UserSignedUp: + payload: + type: object + properties: + displayName: + type: string + description: Name of the user + email: + type: string + format: email + description: Email of the user +``` \ No newline at end of file diff --git a/markdown/docs/reference/bindings/jms.md b/markdown/docs/reference/bindings/jms.md new file mode 100644 index 000000000000..f2598991d9ce --- /dev/null +++ b/markdown/docs/reference/bindings/jms.md @@ -0,0 +1,165 @@ +--- +title: 'jms' +weight: 17 +--- + +# JMS Bindings + +This document defines how to describe JMS-specific information on AsyncAPI. + + +## Versions + +The version of this bindings specification is `0.0.1`. +This is also the `bindingVersion` for all binding objects defined by this specification. +In any given binding object, `latest` MAY alternatively be used to refer to the currently latest published version of this bindings specification. + +## Terminology + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt). + + + +## Protocol + +These bindings use the `jms` [protocol](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#definitionsProtocol) in AsyncAPI documents to denote connections to and interactions with JMS message brokers. + +JMS is not technically a protocol, rather it is an API. A JMS Provider implements the JMS API and may define a protocol for implementing JMS API operations. Regardless, for the purposes of AsyncAPI we can treat it like a "protocol" to enable AsyncAPI definitions that are somewhat portable between various JMS Providers. If necessary, the user is free to combine this binding with other bindings that implement a JMS Provider (e.g. [Apache Pulsar](https://github.com/asyncapi/bindings/tree/master/pulsar), [Amazon SQS](https://github.com/asyncapi/bindings/tree/master/sqs), [IBM MQ](https://github.com/asyncapi/bindings/tree/master/ibmmq), etc.) to detail JMS Provider specific configuration. + +**NOTE** that from protocol version 3.0, this binding is compatible with [Jakarta Messaging](https://jakarta.ee/specifications/messaging). + +## Server Object + +The fields of the standard [Server Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#serverObject) are constrained and interpreted as follows: + +Server Object Field Name | Values for JMS Protocol | Description +---|:---|:--- +`protocol` | `jms` | **REQUIRED**. MUST be `jms` for the scope of this specification. +`url` | e.g., `jms://host:port` | **REQUIRED**. MUST be a URL containing the hostname and port of a JMS Broker. +`protocolVersion` | e.g., `3.1` | **OPTIONAL**, defaults to `3.1`. If present MUST be the version indicator of the JMS API. Valid values are `1.0`, `1.0.1`, `1.0.1a`, `1.0.2`, `1.0.2a`, `1.0.2b`, `1.1`, `2.0`, `2.0a`, `2.1`, or `3.0`, `3.1.`. + + + + +## Server Binding Object + +The JMS [Server Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#server-bindings-object) is defined by a [JSON Schema](json_schemas/server.json), which defines these fields: + +Field Name | Type | Description +---|:---:|--- +`jmsConnectionFactory` | string | **REQUIRED**. The classname of the [ConnectionFactory](https://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html) implementation for the JMS Provider. +`properties` | [Schema Array](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaArray) | **OPTIONAL**. Additional properties to set on the JMS ConnectionFactory implementation for the JMS Provider. +`clientID` | string | **OPTIONAL**. A client identifier for applications that use this JMS connection factory. If the Client ID Policy is set to 'Restricted' (the default), then configuring a Client ID on the [ConnectionFactory](https://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html) prevents more than one JMS client from using a connection from this factory. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +### Examples + +The following example shows a `servers` object with a server binding object for `jms` with JMS specific properties: + +```yaml +servers: + production: + url: jms://my-activemq-broker:61616 + protocol: jms + protocolVersion: '1.1' + description: The production ActiveMQ broker accessed via JMS. + bindings: + jms: + # JMS protocol specific server details + jmsConnectionFactory: org.apache.activemq.ActiveMQConnectionFactory + properties: + - name: disableTimeStampsByDefault + value: false + clientID: my-application-1 +``` + + + +## Channel Binding Object + +The JMS [Channel Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#channel-bindings-object) is defined by a [JSON Schema](json_schemas/channel.json), which defines these fields: + +Field Name | Type | Description +---|:---:|--- +`destination` | string | **OPTIONAL**, defaults to the channel name. The destination (queue) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name according to the JMS Provider. +`destinationType` | string | **OPTIONAL**, defaults to `queue`. The type of destination, which MUST be either `queue`, or `fifo-queue`. SHOULD be specified to document the messaging model (point-to-point, or strict message ordering) supported by this channel. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +### Examples + +The following example shows a `channels` object with two channels, the second having a channel binding object for `jms`: + +```yaml +channels: + user.signup: + description: This application receives command messages from this channel about users to sign up. + bindings: + jms: + destination: user-sign-up + destinationType: fifo-queue + bindingVersion: '0.0.1' + publish: + #... +``` + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Message Binding Object + +The JMS [Message Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#message-bindings-object) is defined by a [JSON Schema](json_schemas/message.json), which defines these fields: + +Field Name | Type | Description +---|:---:|--- +`headers` | [Schema Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject) | **OPTIONAL**. A Schema object containing the definitions for JMS specific headers (so-called protocol headers). This schema MUST be of type `object` and have a `properties` key. Examples of JMS protocol headers are `JMSMessageID`, `JMSTimestamp`, and `JMSCorrelationID`. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +Note that application headers must be specified in the [`headers` field of the standard Message Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#messageObjectHeaders) and are set as [Message Properties](https://docs.oracle.com/javaee/7/api/javax/jms/Message.html#Message%20Properties) of the JMS Message; how they are transmitted is defined by the JMS Provider and need not be considered here. +In contrast, protocol headers such as `JMSMessageID` must be specified in the [`headers` field of the message binding object](#messageBindingObjectHeaders) and are transmitted in the [`headers` section of the JMS message](https://docs.oracle.com/javaee/7/api/javax/jms/Message.html#Message%20Headers). + +### Examples + +The following example shows a `message` object with both application specific headers, and a message binding object for `jms` with JMS specific headers: + +```yaml +message: + messageId: my-message-1 + bindings: + jms: + headers: + # JMS protocol specific message headers + required: + - JMSMessageID + properties: + JMSMessageID: + name: JMSMessageID + description: A unique message identifier. This may be set by your JMS Provider on your behalf. + type: string + JMSReplyTo: + name: JMSReplyTo + description: The queue or topic that the message sender expects replies to. + type: string + headers: + # Application specific message headers + required: + - MyToken + - MyOperationID + properties: + MyToken: + name: MyToken + description: Some sort of identificaton token for the publishing application. + type: string + MyOperationID: + name: MyOperationID + description: Some sort of unique identifier for the application operation to perform. + type: string +``` diff --git a/markdown/docs/reference/bindings/kafka.md b/markdown/docs/reference/bindings/kafka.md new file mode 100644 index 000000000000..4039eae5df44 --- /dev/null +++ b/markdown/docs/reference/bindings/kafka.md @@ -0,0 +1,207 @@ +--- +title: 'kafka' +weight: 18 +--- + +# Kafka Bindings + +This document defines how to describe Kafka-specific information on AsyncAPI. + + + +## Version + +Current version is `0.5.0`. + + + + +## Server Binding Object + +This object contains information about the server representation in Kafka. + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:---:|:---:|:---:|--- +`schemaRegistryUrl` | string (url) | API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used) | OPTIONAL | - +`schemaRegistryVendor` | string | The vendor of Schema Registry and Kafka serdes library that should be used (e.g. `apicurio`, `confluent`, `ibm`, or `karapace`) | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified +`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] + +##### Example + +```yaml +servers: + production: + bindings: + kafka: + schemaRegistryUrl: 'https://my-schema-registry.com' + schemaRegistryVendor: 'confluent' + bindingVersion: '0.5.0' +``` + + + + +## Channel Binding Object + +This object contains information about the channel representation in Kafka (eg. a Kafka topic). + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|--- +`topic` | string | Kafka topic name if different from channel name. | OPTIONAL | - +`partitions` | integer | Number of partitions configured on this topic (useful to know how many parallel consumers you may run). | OPTIONAL | Must be positive +`replicas` | integer | Number of replicas configured on this topic. | OPTIONAL | MUST be positive +`topicConfiguration` | [TopicConfiguration Object](#topicConfiguration) | Topic configuration properties that are relevant for the API. | OPTIONAL | - +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | OPTIONAL [`latest`] | - + + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +channels: + user-signedup: + bindings: + kafka: + topic: 'my-specific-topic-name' + partitions: 20 + replicas: 3 + topicConfiguration: + cleanup.policy: ["delete", "compact"] + retention.ms: 604800000 + retention.bytes: 1000000000 + delete.retention.ms: 86400000 + max.message.bytes: 1048588 + bindingVersion: '0.5.0' +``` + +## TopicConfiguration Object + +This objects contains information about the API relevant topic configuration in Kafka. + +Field Name | Type | Description | Applicability [default] | Constraints +---|:-------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------:|--- +`cleanup.policy` | array | The [`cleanup.policy`](https://kafka.apache.org/documentation/#topicconfigs_cleanup.policy) configuration option. | OPTIONAL | array may only contain `delete` and/or `compact` +`retention.ms` | long | The [`retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_retention.ms) configuration option. | OPTIONAL | see kafka documentation +`retention.bytes` | long | The [`retention.bytes`](https://kafka.apache.org/documentation/#topicconfigs_retention.bytes) configuration option. | OPTIONAL | see kafka documentation +`delete.retention.ms` | long | The [`delete.retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_delete.retention.ms) configuration option. | OPTIONAL | see kafka documentation +`max.message.bytes` | integer | The [`max.message.bytes`](https://kafka.apache.org/documentation/#topicconfigs_max.message.bytes) configuration option. | OPTIONAL | see kafka documentation +`confluent.key.schema.validation` | boolean | It shows whether the schema validation for the message key is enabled. Vendor specific config. | OPTIONAL | - +`confluent.key.subject.name.strategy` | string | The name of the schema lookup strategy for the message key. Vendor specific config. | OPTIONAL | Clients should default to the vendor default if not supplied. +`confluent.value.schema.validation` | boolean | It shows whether the schema validation for the message value is enabled. Vendor specific config. | OPTIONAL | - +`confluent.value.subject.name.strategy` | string | The name of the schema lookup strategy for the message value. Vendor specific config. | OPTIONAL | Clients should default to the vendor default if not supplied. + +This object MAY contain the properties defined above including optional additional properties. + +##### Example + +```yaml +topicConfiguration: + cleanup.policy: ["delete", "compact"] + retention.ms: 604800000 + retention.bytes: 1000000000 + delete.retention.ms: 86400000 + max.message.bytes: 1048588 + confluent.key.schema.validation: true + confluent.key.subject.name.strategy: "TopicNameStrategy" + confluent.value.schema.validation: true + confluent.value.subject.name.strategy: "TopicNameStrategy" +``` + + + +## Operation Binding Object + +This object contains information about the operation representation in Kafka (eg. the way to consume messages) + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:---:|:---:|:---:|--- +`groupId` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | Id of the consumer group. | OPTIONAL | - +`clientId` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | Id of the consumer inside a consumer group. | OPTIONAL | - +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | OPTIONAL [`latest`] | - + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +channels: + user-signedup: +operations: + userSignup: + action: receive + bindings: + kafka: + groupId: + type: string + enum: ['myGroupId'] + clientId: + type: string + enum: ['myClientId'] + bindingVersion: '0.5.0' +``` + + + + +## Message Binding Object + +This object contains information about the message representation in Kafka. + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:-------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------:|--- +`key` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) \| [AVRO Schema Object](https://avro.apache.org/docs/current/spec.html) | The message key. **NOTE**: You can also use the [reference object](referenceObject) way. | OPTIONAL | - +`schemaIdLocation` | string | If a Schema Registry is used when performing this operation, tells where the id of schema is stored (e.g. `header` or `payload`). | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level +`schemaIdPayloadEncoding` | string | Number of bytes or vendor specific values when schema id is encoded in payload (e.g `confluent`/ `apicurio-legacy` / `apicurio-new`). | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level +`schemaLookupStrategy` | string | Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied. | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | OPTIONAL [`latest`] | - + +This object MUST contain only the properties defined above. + +This example is valid for any Confluent compatible schema registry. Here we describe the implementation using the first 4 bytes in payload to store schema identifier. + +```yaml +channels: + test: + address: test-topic + messages: + testMessage: + bindings: + kafka: + key: + type: string + enum: ['myKey'] + schemaIdLocation: 'payload' + schemaIdPayloadEncoding: '4' + bindingVersion: '0.5.0' +``` + +This is another example that describes the use if Apicurio schema registry. We describe the `apicurio-new` way of serializing without details on how it's implemented. We reference a [specific lookup strategy](https://www.apicur.io/registry/docs/apicurio-registry/2.2.x/getting-started/assembly-using-kafka-client-serdes.html#registry-serdes-concepts-strategy_registry) that may be used to retrieve schema Id from registry during serialization. + +```yaml +channels: + test: + address: test-topic + messages: + testMessage: + bindings: + kafka: + key: + type: string + enum: ['myKey'] + schemaIdLocation: 'payload' + schemaIdPayloadEncoding: 'apicurio-new' + schemaLookupStrategy: 'TopicIdStrategy' + bindingVersion: '0.5.0' +``` + +[schemaObject]: https://www.asyncapi.com/docs/reference/specification/v3.0.0-next-major-spec.15#schemaObject +[referenceObject]: https://www.asyncapi.com/docs/reference/specification/v3.0.0-next-major-spec.15#referenceObject diff --git a/markdown/docs/reference/bindings/mercure.md b/markdown/docs/reference/bindings/mercure.md new file mode 100644 index 000000000000..f13432fbb291 --- /dev/null +++ b/markdown/docs/reference/bindings/mercure.md @@ -0,0 +1,48 @@ +--- +title: 'mercure' +weight: 19 +--- + +# Mercure Bindings + +This document defines how to describe Mercure-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/mqtt.md b/markdown/docs/reference/bindings/mqtt.md new file mode 100644 index 000000000000..80441233ed0e --- /dev/null +++ b/markdown/docs/reference/bindings/mqtt.md @@ -0,0 +1,189 @@ +--- +title: 'mqtt' +weight: 20 +--- + +# MQTT Bindings + +This document defines how to describe MQTT-specific information on AsyncAPI. + +It applies to all versions of MQTT, although specific binding fields may only apply to particular versions. + + + +## Version + +Current version is `0.2.0`. + + + + +## Server Binding Object + +This object contains information about the server representation in MQTT. + +##### Fixed Fields + +Field Name | Type | MQTT Versions | Description +---|:---:|:---:|---| +`clientId` | string | 3, 5 | The client identifier. +`cleanSession` | boolean | 3, 5 | Whether to create a persistent connection or not. When `false`, the connection will be persistent. This is called **clean start** in MQTTv5. +`lastWill` | object | 3, 5 | Last Will and Testament configuration. `topic`, `qos`, `message` and `retain` are properties of this object as shown below. +`lastWill.topic` | string | 3, 5 | The topic where the Last Will and Testament message will be sent. +`lastWill.qos` | integer | 3, 5 | Defines how hard the broker/client will try to ensure that the Last Will and Testament message is received. Its value MUST be either 0, 1 or 2. +`lastWill.message` | string | 3, 5 | Last Will message. +`lastWill.retain` | boolean | 3, 5 | Whether the broker should retain the Last Will and Testament message or not. +`keepAlive` | integer | 3, 5 | Interval in seconds of the longest period of time the broker and the client can endure without sending a message. +`sessionExpiryInterval` | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Interval in seconds or a *Schema Object* containing the definition of the interval. The broker maintains a session for a disconnected client until this interval expires. +`maximumPacketSize` | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Number of bytes or a *Schema Object* representing the maximum packet size the client is willing to accept. +`bindingVersion` | string | | The version of this binding. If omitted, "latest" MUST be assumed. | + +This object MUST contain only the properties defined above. + +##### Examples + +```yaml +servers: + production: + bindings: + mqtt: + clientId: guest + cleanSession: true + lastWill: + topic: /last-wills + qos: 2 + message: Guest gone offline. + retain: false + keepAlive: 60 + sessionExpiryInterval: 600 + maximumPacketSize: 1200 + bindingVersion: 0.2.0 +``` +```yaml +servers: + production: + bindings: + mqtt: + sessionExpiryInterval: + type: integer + minimum: 30 + maximum: 1200 + maximumPacketSize: + type: integer + minimum: 256 + bindingVersion: 0.2.0 +``` + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +This object contains information about the operation representation in MQTT. + +##### Fixed Fields + +Field Name | Type | Applies To | MQTT Versions | Description +---|:---:|:---:|:---:|--- +`qos` | integer | Publish, Subscribe | 3, 5 | Defines the Quality of Service (QoS) levels for the message flow between client and server. Its value MUST be either 0 (At most once delivery), 1 (At least once delivery), or 2 (Exactly once delivery). +`retain` | boolean | Publish | 3, 5 | Whether the broker should retain the message or not. +`messageExpiryInterval` | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject]| Publish | 5 | Interval in seconds or a *Schema Object* containing the definition of the lifetime of the message. +`bindingVersion` | string | | | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Examples + +```yaml +channels: + user/signup: + publish: + bindings: + mqtt: + qos: 2 + retain: true + messageExpiryInterval: 60 + bindingVersion: 0.2.0 +``` +```yaml +channels: + user/signup: + publish: + bindings: + mqtt: + messageExpiryInterval: + type: integer + minimum: 30 + maximum: 300 + bindingVersion: 0.2.0 +``` +```yaml +channels: + user/signup: + subscribe: + bindings: + mqtt: + qos: 2 + bindingVersion: 0.2.0 +``` + + + +## Message Binding Object + +This object contains information about the message representation in MQTT. + +##### Fixed Fields + +Field Name | Type | MQTT Versions | Description +---|:---:|:---:|--- +`payloadFormatIndicator` | integer | 5 | Either: **0** (zero): Indicates that the payload is unspecified bytes, or **1**: Indicates that the payload is UTF-8 encoded character data. | +`correlationData` | [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Correlation Data is used by the sender of the request message to identify which request the response message is for when it is received. +`contentType` | string | 5 | String describing the content type of the message payload. This should not conflict with the `contentType` field of the associated AsyncAPI Message object. +`responseTopic` | URI string \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | The topic (channel URI) for a response message. +`bindingVersion` | string | | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Examples + +```yaml +channels: + user/signup: + subscribe: + message: + bindings: + mqtt: + contentType: "application/json" + correlationData: + type: string + format: uuid + bindingVersion: 0.2.0 +``` +```yaml +channels: + userSignup: + address: user/signup + messages: + userSignup: + bindings: + mqtt: + payloadFormatIndicator: 1 + contentType: "application/json" + correlationData: + type: string + format: uuid + responseTopic: + type: string + pattern: "response/client/([a-z1-9]+)" + bindingVersion: 0.2.0 +``` + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject + diff --git a/markdown/docs/reference/bindings/mqtt5.md b/markdown/docs/reference/bindings/mqtt5.md new file mode 100644 index 000000000000..4b33d45b5151 --- /dev/null +++ b/markdown/docs/reference/bindings/mqtt5.md @@ -0,0 +1,79 @@ +--- +title: 'mqtt5' +weight: 21 +--- + +# MQTT 5 Bindings + +This document defines how to describe MQTT 5-specific information on AsyncAPI. + +# **Deprecation Warning**: MQTT version 5 specific bindings are deprecated in favor of [MQTT bindings](../mqtt/README.md) that are not version specific. + + + +## Version + +Current version is `0.2.0`. + + + + +## Server Binding Object + +This object contains information about the server representation in MQTT5. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`sessionExpiryInterval` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) \| integer | Session Expiry Interval in seconds or a Schema Object containing the definition of the interval. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +servers: + production: + bindings: + mqtt5: + sessionExpiryInterval: 60 + bindingVersion: 0.2.0 +``` +```yaml +servers: + production: + bindings: + mqtt5: + sessionExpiryInterval: + type: integer + minimum: 100 + bindingVersion: 0.2.0 +``` + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject diff --git a/markdown/docs/reference/bindings/nats.md b/markdown/docs/reference/bindings/nats.md new file mode 100644 index 000000000000..befeb548d1a0 --- /dev/null +++ b/markdown/docs/reference/bindings/nats.md @@ -0,0 +1,38 @@ +--- +title: 'nats' +weight: 22 +--- + +# NATS Bindings + +This document defines how to describe NATS-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + +## Server Binding Object +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +Field Name | Type | Description +---|:---:|--- +| `queue` | string | Defines the name of the queue to use. It MUST NOT exceed 255 characters. | +| `bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/pulsar.md b/markdown/docs/reference/bindings/pulsar.md new file mode 100644 index 000000000000..99b2cc9b5352 --- /dev/null +++ b/markdown/docs/reference/bindings/pulsar.md @@ -0,0 +1,91 @@ +--- +title: 'pulsar' +weight: 23 +--- + +# Pulsar Bindings +This document defines how to describe Apache Pulsar specific information with AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + +## Server Binding Object + +This object contains information about the server representation in Pulsar. + +##### Fixed Fields + +Field Name | Type | Required | Description | Default value | +---|:---:|:---:|:---|:---| +`tenant` | String | No | The pulsar tenant. If omitted, "public" MUST be assumed. | `public` | +`bindingVersion` | String | No | The version of this binding. If omitted, "latest" MUST be assumed. | `latest` | + +##### Example + +```yaml +servers: + production: + bindings: + pulsar: + tenant: contoso + bindingVersion: '0.1.0' +``` + + +## Channel Binding Object +This object contains information about the channel representation in Pulsar + +##### Fixed Fields + +Field Name | Type | Required | Description | Default value | +---|:---:|:---:|:---|:---| +`namespace` | String | Yes | The namespace the channel is associated with. | N/A | +`persistence` | String | Yes | Persistence of the topic in Pulsar. It MUST be either `persistent` or `non-persistent`. | N/A | +`compaction`| Integer | No | Topic compaction threshold given in Megabytes. | N/A | +`geo-replication` | String[] | No | A list of clusters the topic is replicated to. | N/A | +`retention` | [Retention Definition Object](#retention-definition-object) | No | Topic retention policy. | N/A | +`ttl` | Integer | No | Message time-to-live in seconds. | N/A | +`deduplication` | Boolean | No | Message deduplication. When true, it ensures that each message produced on Pulsar topics is persisted to disk only once. | N/A | +`bindingVersion` | String | No | The version of this binding. If omitted, "latest" MUST be assumed. | `latest` | + + +### Retention Definition Object +The `Retention Definition Object` is used to describe the Pulsar [Retention](https://pulsar.apache.org/docs/cookbooks-retention-expiry/) policy. + +Field Name | Type | Required | Description | Default value | +---|:---:|:---:|:---|:---| +`time`|Integer| No | Time given in Minutes. | `0` | +`size`|Integer| No |Size given in MegaBytes. | `0` | + +##### Example + +```yaml +channels: + user-signedup: + bindings: + pulsar: + namespace: 'staging' + persistence: 'persistent' + compaction: 1000 + geo-replication: + - 'us-east1' + - 'us-west1' + retention: + time: 7 + size: 1000 + ttl: 360 + deduplication: false + bindingVersion: '0.1.0' +``` + + +## Operation binding fields +This object MUST NOT contain any properties. Its name is reserved for future use. + + +## Message binding fields +This object MUST NOT contain any properties. Its name is reserved for future use. \ No newline at end of file diff --git a/markdown/docs/reference/bindings/redis.md b/markdown/docs/reference/bindings/redis.md new file mode 100644 index 000000000000..62737ca2cdd7 --- /dev/null +++ b/markdown/docs/reference/bindings/redis.md @@ -0,0 +1,45 @@ +--- +title: 'redis' +weight: 24 +--- + +# Redis Bindings + +This document defines how to describe Redis-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/scripts.md b/markdown/docs/reference/bindings/scripts.md new file mode 100644 index 000000000000..4932f8b84590 --- /dev/null +++ b/markdown/docs/reference/bindings/scripts.md @@ -0,0 +1,6 @@ +--- +title: 'scripts' +weight: 10 +--- + +The entire `scripts` directory is centrally managed in [.github](https://github.com/asyncapi/.github/) repository. Any changes in this folder should be done in central repository. \ No newline at end of file diff --git a/markdown/docs/reference/bindings/sns.md b/markdown/docs/reference/bindings/sns.md new file mode 100644 index 000000000000..039eee2eb2d6 --- /dev/null +++ b/markdown/docs/reference/bindings/sns.md @@ -0,0 +1,305 @@ +--- +title: 'sns' +weight: 25 +--- + +# SNS Bindings + +This document defines how to describe SNS-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object + +This object contains information about the channel representation in SNS. + +We represent an AsyncAPI Channel with a Topic in SNS. The bindings here allow definition of a topic within SNS. We provide properties on the binding that allow creation of a topic in infrastructure-as-code scenarios. Be aware that although the binding offers that flexibility, it may be more maintainable to specify properties such as SNS Access Control Policy outside of AsyncAPI. + +SNS supports many optional properties. To mark a channel as SNS, but use default values for the channel properties, just use an empty object {}. + +### Fields + +|Field Name | Type | Description| +|---|:---:|---| +| `name` | string | **Required.** The name of the topic. Can be different from the channel name to allow flexibility around AWS resource naming limitations.| +| `ordering` | [ordering](#ordering)| **Optional.** By default, we assume an unordered SNS topic. This field allows configuration of a FIFO SNS Topic. | +| `policy` |[policy](#policy) | **Optional.** The security policy for the SNS Topic | +| `tags` |Object | **Optional.** Key-value pairs that represent AWS tags on the topic. | +|`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.| + +### Schemas + +#### Ordering +|Field Name | Type | Description| +|---|:---:|---| +| `type` | string | **Required.** Defines the type of SNS Topic. Can be either `standard` or `FIFO`. | +| `contentBasedDeduplication` | boolean | **Optional.** Whether the de-duplication of messages should be turned on. Defaults to `false`| + +#### Policy +|Field Name | Type | Description| +|---|:---:|---| +| `statements` | [[Statement](#statement)] | **Required.** An array of Statement objects, each of which controls a permission for this topic | + +#### Statement +|Field Name | Type | Description| +|---|:---:|---| +| `effect` | string |**Required.** Either "Allow" or "Deny"| +| `principal` | string or array of string |**Required.** The AWS account or resource ARN that this statement applies to| +| `action` | string or array of string |**Required.** The SNS permission being allowed or denied e.g. sns:Publish| + +##### Examples + +Just use defaults + +```yaml +channels: + user-signedup: + description: A user has signed up to our service + bindings: + sns: {} +``` + +Minimal definition, just policy + +```yaml +channels: + user-signedup: + description: A user has signed up to our service + bindings: + sns: + policy: + statements: + - effect : Allow + principal: * + action: SNS:Publish +``` + + + +## Operation Binding Object + +This object contains information operation binding in SNS. + +We represent SNS producers via a **subscribe** Operation Object. In simple cases this may not require configuration, and can be shown as an empty SNS Binding Object i.e. {} if you need to explicitly indicate how a producer publishes to the channel. + +We represent SNS consumers via a **publish** Operation Object. These consumers need an SNS Subscription that defines how they consume from SNS i.e. the protocol that they use, and any filters applied. + +The SNS binding does not describe the receiver.If you wish to define the receiver, add a **publish** Operation Binding Object for that receiver. For example, if you send message to an SQS queue from an SNS Topic, you would add a protocol of 'sqs' and an Identifier object for the queue. That identifier could be an ARN of a queue defined outside of the scope of AsyncAPI, but if you wanted to define the receiver you would use the name of a queue defined in an SQS Binding on the **publish** Operation Binding Object. + +We support an array of consumers via the **consumers** field. This allows you to represent multiple protocols consuming an SNS Topic in one file. You may also use it for multiple consumers with the same protocol, instead of representing each consumer in a separate file. + +### Fields + +| Field Name | Type | Applies To | Description | +|---|:---:|:---:|---| +| `topic` | [identifier](#identifier) |Publish, Subscribe| **Optional.** Often we can assume that the SNS Topic is the channel name-we provide this field in case the you need to supply the ARN, or the Topic name is not the channel name in the AsyncAPI document.| +| `consumers` | [[Consumer](#consumer)] |Publish| **Required.** The protocols that listen to this topic and their endpoints.| +| `deliveryPolicy` | [deliveryPolicy](#delivery-policy) |Subscribe| **Optional.** Policy for retries to HTTP. The field is the default for HTTP receivers of the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html) which may be overridden by a specific consumer.| +|`bindingVersion` | string |Publish, Subscribe| **Optional**, defaults to `latest`. The version of this binding.| + +### Schemas + +#### Consumer + +| Field Name | Type | Description | +|---|:---:|---| +| `protocol` | string | **Required.** The protocol that this endpoint receives messages by. Can be `http`, `https`, `email`, `email-json`, `sms`, `sqs`, `application`, `lambda` or `firehose` | +| `endpoint` |[identifier](#identifier)| **Required.** The endpoint messages are delivered to. | +| `filterPolicy` | object | **Optional.** Only receive a subset of messages from the channel, determined by this policy. | +| `filterPolicyScope` | string | **Optional.** Determines whether the FilterPolicy applies to MessageAttributes (default) or MessageBody. | +| `rawMessageDelivery` | boolean | **Required.** If *true* AWS SNS attributes are removed from the body, and for SQS, SNS message attributes are copied to SQS message attributes. If *false* the SNS attributes are included in the body. | +| `redrivePolicy` | [redrivePolicy](#redrive-policy) | **Optional.** Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue. | +| `deliveryPolicy` | [deliveryPolicy](#delivery-policy) | **Optional.** Policy for retries to HTTP. The parameter is for that [SNS Subscription](https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html) and overrides any policy on the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html). | +| `displayName` | string |**Optional.** The display name to use with an SMS subscription | + + +#### Delivery Policy +|Field Name | Type | Description| +|---|:---:|---| +| `minDelayTarget` | integer | **Optional.** The minimum delay for a retry in seconds | +| `maxDelayTarget` | integer | **Optional.** The maximum delay for a retry in seconds | +| `numRetries` | integer | **Optional.** The total number of retries, including immediate, pre-backoff, backoff, and post-backoff retries | +| `numNoDelayRetries` | integer | **Optional.** The number of immediate retries (with no delay) | +| `numMinDelayRetries` | integer | **Optional.** The number of immediate retries (with delay) | +| `numMaxDelayRetries` | integer | **Optional.** The number of post-backoff phase retries, with the maximum delay between retries | +| `backoffFunction` | string, one of: arithmetic, exponential, geometric or linear | **Optional.** The algorithm for backoff between retries | +| `maxReceivesPerSecond` | integer | **Optional.** The maximum number of deliveries per second, per subscription | + +#### Identifier +|Field Name | Type | Description| +|---|:---:|---| +|`url` |string| **Optional.** The endpoint is a URL | +|`email` |string| **Optional.** The endpoint is an email address | +|`phone` |string| **Optional.** The endpoint is a phone number| +|`arn` |string| **Optional.** The target is an [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). For example, for SQS, the identifier may be an ARN, which will be of the form: ["arn:aws:sqs:{region}:{account-id}:{queueName}"](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)| +|`name` |string| **Optional.** The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this **publish** Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field **sqs** binding. We don't use $ref because we are referring, not including. | + +We provide an Identifer Object to support providing the identifier of an externally defined endpoint for this SNS *publication* to target, or an endpoint on another binding against this Operation Object (via the name field). + +#### Redrive Policy + +|Field Name | Type | Description| +|---|:---:|---| +| `deadLetterQueue` |[Identifier](#identifier)| **Required.** The SQS queue to use as a dead letter queue (DLQ). Note that you may have a Redrive Policy to put messages that cannot be delivered to an SQS queue, even if you use another protocol to consume messages from the queue, so it is defined at the level of the SNS Operation Binding Object in a Consumer Object (and is applied as part of an [SNS Subscription](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html)). The SQS Binding describes how to define an SQS Binding that supports defining the target SQS of the Redrive Policy. | +| `maxReceiveCount` |integer| **Optional.** The number of times a message is delivered to the source queue before being moved to the dead-letter queue. Defaults to 10. | + +### Examples + +#### SNS to SQS Pub-Sub + +[](SNS-SQS-Pub-Sub.png) + +We are producing to an SNS channel + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + binding : + sns: {} # Indicates that the channel is an SNS Topic + subscribe: + operationId: sendMessage + description: send messages to the topic + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + name: myQueue + rawMessageDelivery: false +``` + +We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the **publish** Operation Binding. + +In this version, the SQS queue is defined elsewhere, and we just reference via its ARN. It is worth noting that this couples the specification to the AWS *region* and *account*, which are part of the ARN, and if we moved the queue to a new region or account was this specification would need to be updated to reflect that. + + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + publish: + operationId: receiveMessage + description: receive messages from the topic + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + arn: arn:aws:sqs:us-west-2:123456789012:UserSignedUpQueue + rawMessageDelivery: true +``` + +We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the **publish** Operation Binding. + +In this version, the SQS queue is defined in this file, and we reference it by name. For brevity that definition is not shown here. See the SQS Binding Object for more. + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + publish: + operationId: receiveMessage + description: receive messages from the topic + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + name: user-signedup-queue # refers to a queue defined in this file, but not shown in this example + rawMessageDelivery: true + filterPolicy: + reason: + anything-but: password-reset + redrivePolicy: + deadLetterQueue: + name: user-signedup-queue-dlq # refers toa queue defined in this file, but not show in this example +``` + +#### SNS to HTTP Pub Sub + +[](SNS-HTTP.png) + +We are producing to an SNS channel. + +In this version, we define a default delivery policy for any HTTP based consumers + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + bindings: + sns: + policy: + statements: + - effect : Allow + principal: * + action: SNS:Publish + subscribe: + operationId: sendMessage + description: send messages to the topic + bindings: + sns: + deliveryPolicy: + minDelayTarget: 1 + maxDelayTarget: 60 + numRetries: 50 + numNoDelayRetries: 3 + numMinDelayRetries: 2 + numMaxDelayRetries: 35 + backoffFunction: exponential + maxReceivesPerSecond: 10 +``` + +We are consuming an SNS channel, using an HTTP endpoint, which is defined in this AsyncAPI file. For brevity we do not show an http endpoint here. The delivery policy here is defined for the http consumer and overrides any policy set by the producer + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + bindings: + sns: {} # Indicates that the channel is an SNS Topic, but assumes defined by producer + publish: + operationId: receiveMessage + description: receive messages from the topic + bindings: + sns: + - protocol: http + endpoint: + url: http://login.my.com/user/new + filterPolicy: + reason: + anything-but: password-reset + filterPolicyScope: MessageBody + deliveryPolicy: + minDelayTarget: 1 + maxDelayTarget: 120 + numRetries: 30 + numNoDelayRetries: 3 + numMinDelayRetries: 2 + numMaxDelayRetries: 25 + backoffFunction: exponential + maxReceivesPerSecond: 20 + redrivePolicy: + deadLetterQueue: + name: user-signedup-queue-dlq # refers toa queue defined in this file, but not show in this example +``` + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/solace.md b/markdown/docs/reference/bindings/solace.md new file mode 100644 index 000000000000..c546ca40e34c --- /dev/null +++ b/markdown/docs/reference/bindings/solace.md @@ -0,0 +1,207 @@ +--- +title: 'solace' +weight: 26 +--- + +# Solace Bindings + +This document defines how to describe Solace-specific information with AsyncAPI. + + + +## Version + +Current version is `0.4.0`. + + + +## Server Binding Object + +| Field Name | Type | Description | +|------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `bindingVersion` | String | The current version is 0.4.0 | +| `msgVpn` | String | The Virtual Private Network name on the Solace broker. | +| `clientName` | String | A unique client name to use to register to the appliance. If specified, it must be a valid Topic name, and a maximum of 160 bytes in length when encoded as UTF-8. | + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Operation Binding Object + +We need the ability to support several bindings for each operation, see the [Example](#example) section below for details. + +| Field Name | Type | Description | +|------------------|---------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `bindingVersion` | String | The current version is 0.4.0 | +| `destinations` | List of Destination Objects | Destination Objects are described next. | +| `timeToLive` | Integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | Interval in milliseconds or a *Schema Object* containing the definition of the lifetime of the message. | +| `priority` | Integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | The valid priority value range is 0-255 with 0 as the lowest priority and 255 as the highest or a *Schema Object* containing the definition of the priority. | +| `dmqEligible` | Boolean | Set the message to be eligible to be moved to a Dead Message Queue. The default value is false. | + +### Destination Object + +Each destination has the following structure: + +| Field Name | Type | Description | +|----------------------------|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `bindingVersion` | String | The current version is 0.4.0 | +| `destinationType` | Enum | 'queue' or 'topic'. If the type is queue, then the subscriber can bind to the queue, which in turn will subscribe to the topic as represented by the channel name or to the provided topicSubscriptions. | +| `deliveryMode` | Enum | 'direct' or 'persistent'. This determines the quality of service for publishing messages as documented [here.](https://docs.solace.com/Get-Started/Core-Concepts-Message-Delivery-Modes.htm) Default is 'persistent'. | +| `queue.name` | String | The name of the queue, only applicable when destinationType is 'queue'. | +| `queue.topicSubscriptions` | List of String | A list of topics that the queue subscribes to, only applicable when destinationType is 'queue'. If none is given, the queue subscribes to the topic as represented by the channel name. | +| `queue.accessType` | Enum | 'exclusive' or 'nonexclusive'. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Endpoints.htm#Queues) Only applicable when destinationType is 'queue'. | +| `queue.maxMsgSpoolSize` | String | The maximum amount of message spool that the given queue may use. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Message-Spooling.htm#max-spool-usage) Only applicable when destinationType is 'queue'. | +| `queue.maxTtl` | String | The maximum TTL to apply to messages to be spooled. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Configuring-Queues.htm) Only applicable when destinationType is 'queue'. | +| `topic.topicSubscriptions` | List of String | A list of topics that the client subscribes to, only applicable when destinationType is 'topic'. If none is given, the client subscribes to the topic as represented by the channel name. | + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Example with two destinations ## + +Here is an example of when we could need two Solace destinations. + +Imagine a system where there is a schema called Person, and there are topics: + +`person/{personId}/created` + +and + +`person/{personId}/updated` + +and you have one application that receives both events. We also want each to be on its own queue. The AsyncAPI file could look like this: + +```yaml +components: + schemas: + Person: + type: string + messages: + PersonEvent: + payload: + $ref: '#/components/schemas/Person' + schemaFormat: application/vnd.aai.asyncapi+json;version=2.0.0 + contentType: application/json +operations: + addPerson: + action: send + channel: + $ref: '#/channels/address' + messages: + - $ref: '#/channels/address/messages/personEvent' + bindings: + solace: + bindingVersion: 0.4.0 + destinations: + - destinationType: queue + queue: + name: CreatedHREvents + topicSubscriptions: + - person/*/created + - destinationType: queue + queue: + name: UpdatedHREvents + topicSubscriptions: + - person/*/updated + timeToLive: 5000 + priority: 120 + dmqEligible: true + +channels: + person: + address: person/{personId}/{eventType} + parameters: + personId: + schema: + type: string + eventType: + schema: + type: string + messages: + personEvent: + $ref: '#/components/messages/PersonEvent' +asyncapi: 3.0.0 +info: + title: HRApp + version: 0.0.1 +``` + +The expected behavior would be that the application binds to both queues, and each queue has its own topic subscription, one to create and one to updated events. + + +## Example with a wildcard subscription ## + +This example shows how a client could receive all the topics under `person/` using a wildcard subscription: + +```yaml +components: + schemas: + Person: + type: string + messages: + PersonEvent: + payload: + schemaFormat: application/vnd.aai.asyncapi+json;version=3.0.0 + schema: + $ref: '#/components/schemas/Person' + contentType: application/json +operations: + addPerson: + action: send + channel: + $ref: '#/channels/person' + messages: + - $ref: '#/channels/person/messages/personEvent' + bindings: + solace: + bindingVersion: 0.4.0 + destinations: + - destinationType: queue + queue: + name: CreatedHREvents + topicSubscriptions: + - person/*/created + - destinationType: queue + queue: + name: UpdatedHREvents + topicSubscriptions: + - person/*/updated + timeToLive: 5000 + priority: 120 + dmqEligible: true + +channels: + person: + address: person/{personId}/{eventType} + parameters: + personId: + description: The machine readable id of the person + eventType: + enum: + - create + - delete + messages: + personEvent: + $ref: '#/components/messages/PersonEvent' +asyncapi: 3.0.0 +info: + title: HRApp + version: 0.0.1 +``` + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject diff --git a/markdown/docs/reference/bindings/sqs.md b/markdown/docs/reference/bindings/sqs.md new file mode 100644 index 000000000000..a52dbd8d5666 --- /dev/null +++ b/markdown/docs/reference/bindings/sqs.md @@ -0,0 +1,247 @@ +--- +title: 'sqs' +weight: 27 +--- + +# SQS Bindings + +This document defines how to describe SQS-specific information on AsyncAPI. + +SQS can be used both stand-alone as a point-to-point and paired with SNS and as a publish-subscribe channel (where SQS is the endpoint that SNS delivers messages to). For this reason we define a Queue schema, and reference that schema from both a Channel Binding Object and a **publish** Operation Binding Object. + +For point-to-point scenarios, use the Channel Binding Object, as producers send to the queue and consumers receive from it directly. + +For publish-subscribe scenarios, use as a **publish** Operation Binding Object, as the producer sends to SNS and the consumer receives via SQS. + + + +## Version + +Current version is `0.2.0`. + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object + +Use the Channel Binding Operation for Point-to-Point SQS channels. + +There are three likely scenarios for use of the Channel Binding Object: + +- One file defines both publish and subscribe operations, for example if we were implementing the work queue pattern to offload work from an HTTP API endpoint to a worker process. In this case the channel would be defined on the Channel Object in that single file. +- The producer and consumer both have an AsyncAPI specification file, and the producer is raising an event, for example interop between microservices, and the producer 'owns' the channel definition and thus has the SQS Binding on its Channel Object. +- The producer and consumer both have an AsyncAPI specification file, and the consumer receives commands, for example interop between microservices, and the consumer 'owns' the channel definition and thus has the SQS Binding on its Channel Object. + +An SQS queue can set up a Dead Letter Queue as part of a Redelivery Policy. To support this requirement, the Channel Binding Object allows you to define both a Queue Object to use as the Channel or target in a *publish* Operation and a Dead Letter Queue. You can then refer to the Dead letter Queue in the Redrive Policy using the Identifier Object and setting the *name* field to match the *name* field of your Dead Letter Queue Object. (If you define the DLQ externally, the Identifier also supports an ARN). + +### Fields +|Field Name | Type | Description| +|---|:---:|---| +| `queue` | [Queue](#queue)| **Required.** A definition of the queue that will be used as the channel. | +| `deadLetterQueue` | [Queue](#queue)| **Optional.** A definition of the queue that will be used for un-processable messages. | +|`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.| + +### Schemas + +#### Queue +|Field Name | Type | Description| +|---|:---:|---| +| `name` | string | **Required.** The name of the queue. When an [SNS Operation Binding Object]() references an SQS queue by name, the identifier should be the one in this field.| +| `fifoQueue` | boolean | **Required.** Is this a FIFO queue? | +| `deduplicationScope` | string | **Optional.** Specifies whether message deduplication occurs at the message group or queue level. Valid values are `messageGroup` and `queue`. **This property applies only to high throughput for FIFO queues.** | +| `fifoThroughputLimit` | string | **Optional.** Specifies whether the FIFO queue throughput quota applies to the entire queue or per message group. Valid values are `perQueue` and `perMessageGroupId`. **The `perMessageGroupId` value is allowed only when the value for DeduplicationScope is `messageGroup`. Setting both these values as such will enable high throughput on a FIFO queue. As above, this property applies only to high throughput for FIFO queues.** | +| `deliveryDelay` | integer | **Optional.** The number of seconds to delay before a message sent to the queue can be received. Used to create a *delay queue*. Range is 0 to 15 minutes. Defaults to 0. | +| `visibilityTimeout` |integer| **Optional.** The length of time, in seconds, that a consumer locks a message - hiding it from reads - before it is unlocked and can be read again. Range from 0 to 12 hours (43200 seconds). Defaults to 30 seconds. | +| `receiveMessageWaitTime` |integer| **Optional.** Determines if the queue uses [short polling](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html) or [long polling](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html). Set to zero (the default) the queue reads available messages and returns immediately. Set to a non-zero integer, long polling waits the specified number of seconds for messages to arrive before returning. | +| `messageRetentionPeriod` |integer| **Optional.** How long to retain a message on the queue in seconds, unless deleted. The range is 60 (1 minute) to 1,209,600 (14 days). The default is 345,600 (4 days). | +| `redrivePolicy` | [Redrive Policy](#redrive-policy) | **Optional.** Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.| +| `policy` |[Policy](#policy) | **Optional.** The security policy for the SQS Queue | +| `tags` |Object | **Optional.** Key-value pairs that represent AWS tags on the queue. | + +#### Identifier +|Field Name | Type | Description| +|---|:---:|---| +|`arn` |string| **Optional.** The target is an [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). For example, for SQS, the identifier may be an ARN, which will be of the form: ["arn:aws:sqs:{region}:{account-id}:{queueName}"](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)| +|`name` |string| **Optional.** The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this **publish** Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field **sqs** binding| + +#### Policy +|Field Name | Type | Description| +|---|:---:|---| +| `Statements` | [Statement](#statement) | **Required.** An array of Statement objects, each of which controls a permission for this queue. | + +#### Redrive Policy +|Field Name | Type | Description| +|---|:---:|---| +| `deadLetterQueue` |[Identifier](#identifier)| The SQS queue to use as a dead letter queue (DLQ) | +| `maxReceiveCount` |integer| **Optional.** The number of times a message is delivered to the source queue before being moved to the dead-letter queue. Default is 10. | + +#### Statement +|Field Name | Type | Description| +|---|:---:|---| +| `effect` | string |**Required.** Either "Allow" or "Deny"| +| `principal` | string or array of string |**Required.** The AWS account or resource ARN that this statement applies to| +| `action` | string or array of string |**Required.** The SQS permission being allowed or denied e.g. sqs:ReceiveMessage | + + + + +## Operation Binding Object + +### SQS Point-To-Point + +Because we have defined Queue as part of the Channel Binding Binding object, we do not require Binding information for the **publish** Operation Object of the **subscribe** Operation Object. You can use an empty Queue object ({}) to denote the Binding on the Operation Object, if you want to indicate the protocol used to send or receive for generation purposes such as Infrastructure As Code. + +### SNS to SQS Pub-Sub + +Use the Operation Binding Object when SQS is listening to an SNS Topic. In this case we need to define both an SQS Operation Binding Objects on the receiver **publish** Operation Object to represent the queue definition and we need to define an SNS Operation Binding Object to define the Subscription to SNS that makes your queue a receiver of that endpoint. + +Assuming you have separate AsyncAPI specifications for the producer and the consumer, we would assume the following bindings would appear for an SNS producer and an SQS consumer. + +Producer: SNS Channel Binding Object, SNS **subscribe** Operation Binding Object [if required] +Consumer: SNS **publish** Operation Binding Object, SQS **publish** Operation Binding Object + +- We assume that the SNS binding information only needs to be present in the producer file (although defining it in both is allowable) and any infrastructure as code dependencies can recognize this. + + +On an Operation Binding Object we support an array of Queue objects. Members of this array may be Queue Objects that define the *endpoint* field required by an [SNS Operation Object]() delivering by the SQS protocol or Queue Objects that define the Dead Letter Queue used by either the Redrive Policy of the SNS Subscription (see the SNS Binding Object) or the [Redrive Policy of the SQS Queue](#redrive-policy). The name of the Queue Object is used by an Identifier field on either the *endpoint* field of the SNS Operation Object of *deadLetterQueue* on the Redrive Policy to identify the required member of this array. + + +### Fields +|Field Name | Type | Description| +|---|:---:|---| +| `queues` | [[Queue](#queue)]| **Required.** Queue objects that are either the *endpoint* for an SNS Operation Binding Object, or the *deadLetterQueue* of the SQS Operation Binding Object | +|`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.| + +### Examples + +#### SQS Point-To-Point + +[](SQS-Point-To-Point.png) + +In this example, we are using SQS for a point-to-point channel. For this example, we assume that we are defining two microservices that communicate over a shared SQS channel, with the consumer receiving events over that channel and the producer owning the channel definition. + +The producer file would look like this: + +```yaml +channels: + user-signedup: + bindings: + sqs: + queue: + name: user-signedup-queue + fifoQueue: false + receiveMessageWaitTime: 4 + redrivePolicy: + deadLetterQueue: + name: user-signedup-dlq + policy: + statements: + - effect : Allow + principal: * + action: Sqs:SendMessage + - effect : Allow + principal: * + action: Sqs:ReceiveMessage + deadLetterQueue: + name: user-signedup-dlq + messageRetentionPeriod: 1209600 + fifoQueue: false + subscribe: + operationId: sendMessage + description: sends messages when a user has signed up + bindings: + sqs: {} + +``` +In this case we can minimize duplicated information by omitting the binding in our specification, and assume it is picked up from the producer file. We can use an empty object to indicate the SQS Binding on the **publish** Operation Object, if need a marker for generation, otherwise we could omit the Operation Binding Object. + +```yaml +channels: + user-signedup: + publish: + operationId: receiveMessage + description: receives a messages when a user has signed up + bindings: + sqs: {} + +``` + +#### SNS to SQS Pub-Sub + +[](SNS-SQS-Pub-Sub.png) + +In this example, we are using SNS for the channel, and SQS to receive from SNS. + + +The producer files looks like this (see the [SNS Binding]() for more). + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + binding : + sns: {} # Indicates that the channel is an SNS Topic + subscribe: + operationId: sendMessage + description: send messages to the topic + bindings: + sns: + policy: + statements: + - effect : Allow + principal: * + action: SNS:Publish +``` + +And the consumer file would look like this. Note that for simplicity, we choose not to repeat the SNS Binding on the Consumer as it does not 'own' the channel. + + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + publish: + operationId: receiveMessage + description: receive messages from the topic + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + name: user-signedup-queue + rawMessageDelivery: true + filterPolicy: + attributes: + reason: + anything-but: password-reset + redrivePolicy: + deadLetterQueue: + name: user-signedup-queue-dlq + sqs: + queues: + - name: user-signedup-queue + fifoQueue: false + receiveMessageWaitTime: 4 + policy: + statements: + - effect : Allow + principal: * + action: Sqs:SendMessage + - effect : Allow + principal: * + action: Sqs:ReceiveMessage + - name: user-signedup-dlq + messageRetentionPeriod: 1209600 + fifoQueue: false +``` + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/stomp.md b/markdown/docs/reference/bindings/stomp.md new file mode 100644 index 000000000000..5e20d85032f1 --- /dev/null +++ b/markdown/docs/reference/bindings/stomp.md @@ -0,0 +1,45 @@ +--- +title: 'stomp' +weight: 28 +--- + +# STOMP Bindings + +This document defines how to describe STOMP-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/websockets.md b/markdown/docs/reference/bindings/websockets.md new file mode 100644 index 000000000000..35d2b8641441 --- /dev/null +++ b/markdown/docs/reference/bindings/websockets.md @@ -0,0 +1,58 @@ +--- +title: 'websockets' +weight: 29 +--- + +# WebSockets Bindings + +This document defines how to describe WebSockets-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Channel Binding Object + +When using WebSockets, the channel represents the connection. Unlike other protocols that support multiple virtual channels (topics, routing keys, etc.) per connection, WebSockets doesn't support virtual channels or, put it another way, there's only one channel and its characteristics are strongly related to the protocol used for the handshake, i.e., HTTP. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`method` | string | The HTTP method to use when establishing the connection. Its value MUST be either `GET` or `POST`. +`query` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for each query parameter. This schema MUST be of type `object` and have a `properties` key. +`headers` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions of the HTTP headers to use when establishing the connection. This schema MUST be of type `object` and have a `properties` key. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject \ No newline at end of file diff --git a/public/img/docs/SNS-HTTP.png b/public/img/docs/SNS-HTTP.png new file mode 100644 index 0000000000000000000000000000000000000000..72e52c730be93cbf230db6336eb611958fc3adf2 GIT binary patch literal 50765 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 Q7T||5IcxkFeI@Dt02psn>Hq)$ literal 0 HcmV?d00001 diff --git a/public/img/docs/SQS-Point-To-Point.png b/public/img/docs/SQS-Point-To-Point.png new file mode 100644 index 0000000000000000000000000000000000000000..a94cfc7b95d2781110ce82cd453c21bf43e30499 GIT binary patch literal 37204 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 literal 0 HcmV?d00001