-
Notifications
You must be signed in to change notification settings - Fork 59
feat: added support for AsyncAPI v3 #367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
Also cleaned up the spec to make it very clear that step-object can be oneOf openapi-step-object or asyncapi-step-object or workflow-step-object For AsyncAPI we really need support for timeout, fork and join. However, these are also useful for OpenAPI so added it at the base step object. For OpenAPI we need at least one successCriteria but for AsyncAPI it can be optional.
|
Let's have you join Nick, Mike and myself next week and the next few weeks for some follow up on how this works. We started meeting to discuss the best approach forward as well. As this would fundamentally alter the spec we'll definitely need a bit of time to go through what you have here and what we are looking in to.. see what might overlap, etc. Shoot me a msg on slack with your email so I can add you to our conversations there. |
|
Here is a simple example just for your reference. arazzo: "1.0.1"
info:
title: "Workflow for placing an Order"
version: "1.0.0"
sourceDescriptions:
- name: "OrderApi"
url: "./openapi/order.yaml"
type: "openapi"
- name: "AsyncOrderApi"
url: "./asyncapi/order.yaml"
type: "asyncapi"
workflows:
- workflowId: "PlaceOrder"
inputs:
required:
- "CreateOrder"
type: "object"
properties:
CreateOrder:
required:
- "orderRequestId"
- "productId"
- "quantity"
type: "object"
properties:
orderRequestId:
type: "string"
productId:
type: "integer"
quantity:
type: "integer"
steps:
- stepId: "CreateOrder"
operationId: "$sourceDescriptions.AsyncOrderApi.PlaceOrder"
stepType: "asyncapi"
action: "send"
parameters:
- name: "orderRequestId"
in: "header"
value: "$inputs.CreateOrder.orderRequestId"
requestBody:
payload:
productId: "$inputs.CreateOrder.productId"
quantity: "$inputs.CreateOrder.quantity"
outputs:
orderRequestId: "$message.header.orderRequestId"
- stepId: "ConfirmOrder"
operationId: "$sourceDescriptions.AsyncOrderApi.PlaceOrder"
stepType: "asyncapi"
action: "receive"
correlationId: "$steps.CreateOrder.outputs.orderRequestId"
timeout: 6000
outputs:
orderId: "$message.body.orderId"
- stepId: "GetOrderDetails"
operationId: "$sourceDescriptions.OrderApi.getOrder"
parameters:
- name: "orderId"
in: "path"
value: "$steps.ConfirmOrder.outputs.orderId"
successCriteria:
- condition: "$statusCode == 200"
components: {} |
|
As discussed, here is an example with fork and join arazzo: "1.0.1"
info:
title: "Workflow for placing an Order"
version: "1.0.0"
sourceDescriptions:
- name: "OrderApi"
url: "./openapi/order.yaml"
type: "openapi"
- name: "AsyncOrderApi"
url: "./asyncapi/order.yaml"
type: "asyncapi"
workflows:
- workflowId: "PlaceOrder"
inputs:
required:
- "CreateOrder"
type: "object"
properties:
CreateOrder:
required:
- "orderRequestId"
- "productId"
- "quantity"
type: "object"
properties:
orderRequestId:
type: "string"
productId:
type: "integer"
quantity:
type: "integer"
steps:
- stepType: "asyncapi"
stepId: "ConfirmOrder"
operationId: "$sourceDescriptions.AsyncOrderApi.PlaceOrder"
action: "receive"
correlationId: "$inputs.CreateOrder.orderRequestId"
fork: true # Converts ConfirmOrder to a Non Blocking Step
timeout: 6000
outputs:
orderId: "$message.body.orderId"
- stepType: "asyncapi"
stepId: "CreateOrder"
operationId: "$sourceDescriptions.AsyncOrderApi.PlaceOrder"
action: "send"
parameters:
- name: "orderRequestId"
in: "header"
value: "$inputs.CreateOrder.orderRequestId"
requestBody:
payload:
productId: "$inputs.CreateOrder.productId"
quantity: "$inputs.CreateOrder.quantity"
- stepId: "GetOrderDetails"
operationId: "$sourceDescriptions.OrderApi.getOrder"
join: # Waits for ConfirmOrder to complete or timeout
- ConfirmOrder # Can also be 'true' to join/wait all
parameters:
- name: "orderId"
in: "path"
value: "$steps.ConfirmOrder.outputs.orderId"
successCriteria:
- condition: "$statusCode == 200"
components: {} |
|
Thanks @nashjain - I will try to propose changes to the specification based on the examples later this week. There will no doubt be a few finer grained points that we'll need to discuss |
|
Taking the above examples into consideration here's a proposal outlining the specification changes to support AsyncAPI in v1.1.0. I've also provided an updated example which complies to the this proposal below. If we're in general agreement, I'll update this PR to reflect the proposal. Summary of the specification changes to add AsyncAPI support (not exhaustive)Source Description Object
|
|
Thanks @frankkilcommins The proposal mostly looks good to me. I just need sometime to think through a couple of items. I'm currently in Australia. Next week, once I'm back we could jump on a call to discuss and close it. |
|
@nashjain We discussed a bit about the removal of fork: true and kind: async implicitly indicates a fork, so removing that and then using dependsOn instead of join since we have dependsOn in the spec already elsewhere. Also the nature of a "fire and forget" (dont need response) vs "fire and wait for a response" which basically assumes if a dependsOn isn't indicating a given async kind that has a correlation id (or maybe thats not even needed) that it would indicate a fire/forget scenario. What do you think? If you can join the next meeting we can discuss on that call that would be great. |
|
Do we even need
But I also have a more general question/concern. I'm not clear about tooling support requirements. Provided AsyncAPI spec supports so many different protocols (websockets, kafka, mqtt, grpc, sns, sqs, etc, etc) would tooling be expected to support all of those? Or some subset? Or what? My concern is we may have almost no support from tooling as I don't even understand how "receive" can be implemented for some of those protocols. |
The proposal for
It's not set in stone at this point and as you mention the
Arazzo itself is agnostic to the specific protocols that can be modelled within AsyncAPI. Tooling implementations may choose to support a subset of protocols depending on use case or runtime environment. We can look to state a documented set of "Recommended" protocols for tooling advertising Arazzo AsyncAPI support. Off the top of my head (not final), something like:
To help perhaps tease out some of the further details, I've created a repo with some examples. Would be great for others to chime in and/or review/enrich the examples. See https://github.com/frankkilcommins/arazzo-examples for details. |
|
@frankkilcommins — +1 on |
I disagree. This requires more validation in fact and makes it worse. See example below. It just adds unnecessary duplication and also inconsistency:
Docs generators can display it nicely.
This makes sense in general but then those steps won't be linked to any source descriptions so let's consider it later when those extensibility is introduced
@mikeschinkel, any pros/cons you have in mind? |
|
@RomanHotsiy — My +1 came from being on the bi-weekly Arazzo call with @frankkilcommins and @kevinduffey where we discussed this and @frankkilcommins explained the rationale which I remember seemed logical and useful and where the three of us agreed, though I do not remember the specifics. I will let @frankkilcommins elaborate again, and/or maybe @kevinduffey can chime in. If you are available Wednesday Nov 26th 7pm EET you could join the next call if you like. |
While we've tried to incorporate as much as possible from #270 not everything is covered.