AsyncAPI gets a new version 3.0 and new operations
Almost one year ago, I talked about AsyncAPI 2.6
and how confusing its publish
and subscribe
operations can be in my Understanding AsyncAPI's publish & subscribe semantics with an example post.
Since then, a new 3.0
version of AsyncAPI has been released with breaking changes and a totally new send
and receive
operations.
In this blog post, I want to revisit the example from last year and show how to rewrite it for AsyncAPI 3.0
with the new send
and receive
operations.
AsyncAPI 3.0
AsyncAPI 3.0
was released in December 2023. Since it's a major version, it has some breaking changes. These two pages does a good job explaining the changes and the rationale behind them:
I won’t go through all the changes. For me, the biggest change is the separation of operations and channels, and changing publish
and subscribe
operations to send
and receive
.
Recap: Publish and subscribe operations in AsyncAPI 2.6
As a recap, AsyncAPI 2.6
has the following publish
and subscribe
operations with these semantics:
In 2.6
, publish
and subscribe
operations are from user's perspective.
New: Send and receive operations in AsyncAPI 3.0
In 3.0
, the publish
and subscribe
operations are replaced with send
and receive
operations. In Migrating to v3 page, the rationale is given as follows:
In v2, the publish and subscribe operations consistently caused confusion, even among those familiar with the intricacies.
When you specified publish, it implied that others could publish to this channel since your application subscribed to it. Conversely, subscribe meant that others could subscribe because your application was the one publishing.
In v3, these operations have been entirely replaced with an action property that clearly indicates what your application does. That eliminates ambiguities related to other parties or differing perspectives.
While I agree that publish
and subscribe
were confusing, I'm not sure if send
and receive
are less confusing. You still need to talk about whose perspective when defining these operations. AsyncAPI docs talk about application but that's not clear either. Does application refer to the code sending the message (user) or the code receiving the message (server)?
In Async 3.0
, send
and receive
operations are from server's perspective. An example will clarify.
Account and Email Services
Let’s revisit our example from last year. You have two microservices: Account Service
emits an userSignedUp
event and Email Service
receives that event:
How do you define such an architecture in AsyncAPI 2.6
vs 3.0
?
Account Service
For Account Service
, in 2.6
, you had to define a channel with subscribe
operation because the user has to subscribe to receive messages:
asyncapi: 2.6.0
channels:
user/signedup:
subscribe:
operationId: publishUserSignedUp
message:
$ref: '#/components/messages/userSignedUp'
In 3.0
, the channel does not have an operation anymore. Instead, there's a new publishUserSignedUp
operation with send
action that refers to the channel. This is because the server sends the message:
asyncapi: 3.0.0
channels:
user/signedup:
address: user/signedup
messages:
publishUserSignedUp.message:
$ref: '#/components/messages/userSignedUp'
operations:
publishUserSignedUp:
action: send
channel:
$ref: '#/channels/user~1signedup'
messages:
- $ref: '#/channels/user~1signedup/messages/publishUserSignedUp.message'
Email Service
Similarly, in Email Service
, in 2.6
, you had to define a publish
operation because the user had to publish a message to the server:
asyncapi: 2.6.0
channels:
user/signedup:
publish:
operationId: receiveUserSignedUp
message:
$ref : '#/components/messages/userSignedUp'
However, in 3.0
, the server receives a message, so the operation has receive
action:
asyncapi: 3.0.0
channels:
user/signedup:
address: user/signedup
messages:
receiveUserSignedUp.message:
$ref: '#/components/messages/userSignedUp'
operations:
receiveUserSignedUp:
action: receive
channel:
$ref: '#/channels/user~1signedup'
messages:
- $ref: '#/channels/user~1signedup/messages/receiveUserSignedUp.message'
In this blog post, I explored a small part of AsyncAPI and explained the differences between 2.6
operations publish
and subscribe
and 3.0
operations send
and receive
. In a nutshell, in 2.6
, you need to think from user's perspective and in 3.0
in server's perspective when you define these operations.
If you’re interested in learning more, I have a talk on CloudEvents and AsyncAPI and a repo with some samples:
Originally published at https://atamel.dev.