-
-
Notifications
You must be signed in to change notification settings - Fork 269
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
Do you have a simpler example ? #31
Comments
Hi @jogelin, I see a few problems here: Your code is asynchronous, your approach does notWhat you're trying to achieve, as per my understanding, is not asynchronous. You said:
If your app has to wait, then this is the first sign that it's not async. If you still want to do it like this I'll better suggest you use an HTTP API instead of WebSockets communication, because your approach is based on request/response. Of course, you can always implement RPC-style APIs using message-driven communication but that's a land I don't recommend you to walk. However, let's talk about it. RPC
There's no link between messages. At least not if you don't define it. You can create a unique identifier for every message and respond back with a message referencing it. For instance, you send a message like this one: {
"id": "1234",
"status": "active"
} and the server will respond back with a message like this: {
"id": "5678",
"responseTo": "1234",
"users": [
{ "id": "fmvilas", "name": "Fran" },
{ "id": "jogelin", "name": "Jogelin" }
]
} That will perfectly work, however, what you would be doing there is exactly what you get with an HTTP API. So I'd not mess around with RPC over WebSockets and would use an HTTP API instead. Event-driven communicationIf you can change how your app works I'd suggest you to events instead of requests and responses. An example could be:
You have to think about the messages in step 3 and 4 as fire and forget. You just communicate that "something happened". You never expect a response. I hope this sheds some light on your problem. I'm happy to help further if you need it. |
Thanks a lot. I knew I was wrong in my understanding of async, I just need a confirmation and you answered it perfectly. You rock ! |
Thanks! I'm glad it helped. Feel free to ask whenever you have questions 👍 |
Hum..... so I have a question :p Since your great answer, I am trying to specify my api with OpenApi but I would like to keep a Message Driven way....is that possible ?....:) I am working on an app using:
And the goal is to be able to communicate directly the actions of the frontend to the backend without mapping each of the actions to an http endpoint. The backend will also answer to the frontend using message formats. It is why I choosed websocket but I completly agree, websocket should not be used to synchronous requests. So I think to have only one POST endpoint on my service which is receiving a message et returning another message. Example:
My first try:
But it looks very complex (it is why I feel that asyncapi was good for that) so if you have any advices...? |
Not sure I understand why you chose OpenAPI if you want to do it with messages. What I said previously, is that only the first call to grab the current status of users can be documented using OpenAPI as it makes sense because it's a synchronous operation over HTTP. Then, the rest of operations can be documented using AsyncAPI because they are events over WebSockets. If you want to go the full way with events it's also fine and you can do it. So let's break this up into many cases: OpenAPI + AsyncAPIOpenAPI file to describe the first operation (grabbing the current status of users): paths:
/users_status
get:
responses:
200:
content:
schema:
$ref: "#/components/schemas/UserStatusResponse"
components:
schemas:
UserStatusResponse:
type: array
items:
type: object
properties:
username:
type: string
full_name:
type: string
status:
type: string
enum:
- active
- busy
- away
- disconnected And now the AsyncAPI file to describe the events: topics:
yourcompany.user.1.0.event.user.status.list.changed:
subscribe:
$ref: "#/components/messages/UserStatusListChangedMessage"
publish:
$ref: "#/components/messages/UserStatusListChangedMessage"
yourcompany.user.1.0.event.user.status.changed:
subscribe:
$ref: "#/components/messages/UserStatusChangedMessage"
publish:
$ref: "#/components/messages/UserStatusChangedMessage"
components:
messages:
UserStatusListChangedMessage:
payload:
type: array
items:
$ref: "#/components/schemas/user"
UserStatusChangedMessage:
payload:
$ref: "#/components/schemas/user"
schemas:
user:
type: object
properties:
username:
type: string
full_name:
type: string
status:
type: string
enum:
- active
- busy
- away
- disconnected Only AsyncAPIIf you choose to only use events, then you have to change your approach. When you connect to the server using WebSockets you'll send a message saying you just connected. It's very easy to fall into the temptation of creating a message saying: "Give me the list of active users". If you want to use event-driven design the message should never be an action (i.e. Give me) but instead, it should be an event (i.e. I just connected). Here's the AsyncAPI file (roughly) for this: topics:
yourcompany.user.1.0.event.user.status.list.changed:
subscribe:
$ref: "#/components/messages/UserStatusListChangedMessage"
publish:
$ref: "#/components/messages/UserStatusListChangedMessage"
yourcompany.user.1.0.event.user.status.changed:
subscribe:
$ref: "#/components/messages/UserStatusChangedMessage"
publish:
$ref: "#/components/messages/UserStatusChangedMessage"
yourcompany.frontend.1.0.event.connected:
subscribe:
$ref: "#/components/messages/FrontendConnectedMessage"
publish:
$ref: "#/components/messages/FrontendConnectedMessage"
components:
messages:
UserStatusListChangedMessage:
payload:
type: array
items:
$ref: "#/components/schemas/user"
UserStatusChangedMessage:
payload:
$ref: "#/components/schemas/user"
FrontendConnectedMessage:
payload:
$ref: "#/components/schemas/FrontendConnected"
schemas:
user:
type: object
properties:
username:
type: string
full_name:
type: string
status:
type: string
enum:
- active
- busy
- away
- disconnected
FrontendConnected:
type: object You might be wondering why I'm always duplicating Hope it helps. |
You might want to join our Slack channel: https://async-apis-slack.herokuapp.com/ |
After a some researches about "how to document message-driven communication", I found your framework which looks very good but There is something that I don't understand...
I am beginner in the "message driven" way of communication but today I have an app using websockets and I didn't sucess to write the spec using asyncapi.
A simple example to display a list of filtered users:
Every call is asynchrone. So I tried to specify that using the asyncapi format:
What I misunderstand is the link between request message and response message. In your singup example, I am mixing the role of the "accounts.1.0.event.user.signup" message. It look like the reponse message but it's a topic that we should subscribe....
The text was updated successfully, but these errors were encountered: