Introduction
In the Create an AsyncAPI Document for a Slackbot with WebSockets tutorial, you learned how to write an AsyncAPI document for a Slackbot Heart-Counter
that actively monitored reactions associated with a message. In this lesson, let's go a step further. After receiving a reaction, Heart-Counter
responds via a message back to the Slack server through WebSocket to confirm the event reception.
The interaction where the Slackbot acknowledges the event and replies with a specific response sets the stage for the Request/Reply messaging pattern discussed in this context.
Refer to the Request/Reply pattern tutorial for an introduction to its implementation.
Background context
The Request-Reply Messaging Pattern in AsyncAPI is an exciting and highly anticipated feature. The messaging pattern mirrors a traditional conversation, where one "requester" entity initiates a query or request, and the "responder" entity provides a specific and expected response. The messaging pattern can work in both synchronous and asynchronous environments and is very beneficial to decouple components by allowing them to operate independently in a distributed system.
Define messages
In the Heart-Counter
tutorial, you dealt with the hello
event triggered when the WebSocket connection was established and the reaction
event expected when a new reaction-added event was triggered.
In this tutorial, you'll add the acknowledge
message to your AsyncAPI document to represent the acknowledgment sent by the Slack application back to the server to indicate that it has successfully received the message.
1components:
2 messages:
3 reaction:
4 summary: Action triggered when the channel receives a new reaction-added event
5 payload:
6 $ref: '#/components/schemas/reaction'
7 hello:
8 summary: Action triggered when a successful WebSocket connection is established
9 payload:
10 $ref: '#/components/schemas/hello'
11 acknowledge:
12 summary: Acknowledgement response sent to Server
13 payload:
14 $ref: '#/components/schemas/acknowledge'
Define schemas
Previously, the reaction
schema was simplified to include the event
payload. However, in this instance, you will be able to elaborate on the schema for the complete request it is expected to receive.
Remember
The sample request and response payloads are extracted from Slack's official documentation.
1 schemas:
2 hello:
3 type: object
4 properties:
5 type:
6 type: string
7 description: A hello string confirming WebSocket connection
8 connection_info:
9 type: object
10 properties:
11 app_id:
12 type: string
13 num_connections:
14 type: integer
15 debug_info:
16 type: object
17 properties:
18 host:
19 type: string
20 started:
21 type: string
22 build_number:
23 type: integer
24 approximate_connection_time:
25 type: integer
26 reaction:
27 type: object
28 properties:
29 envelope_id:
30 type: string
31 description: 'Unique ID assigned to payload'
32 payload:
33 type: object
34 description: 'Payload of the reaction added event'
35 properties:
36 token:
37 type: string
38 team_id:
39 type: string
40 event:
41 type: object
42 properties:
43 user:
44 type: string
45 description: User ID who performed this event
46 reaction:
47 type: string
48 description: The only reaction that you need is a heart emoji
49 item_user:
50 type: string
51 description: |
52 User ID that created the original item that has been reacted
53 to
54 item:
55 type: object
56 properties:
57 channel:
58 type: string
59 description: Channel information of original message
60 ts:
61 type: string
62 description: Timestamp information of original message
63 event_ts:
64 type: string
65 description: Reaction timestamp
66 type:
67 type: string
68 accepts_response_payload:
69 type: boolean
Additionally, you will also be adding the acknowledge
schema that makes use of the envelope_id
attribute to send a reply back to Slack acknowledging that event has been received.
1 acknowledge:
2 type: object
3 properties:
4 envelope_id:
5 type: string
6 description: 'Unique ID of acknowledged payload'
7 payload:
8 type: object
9 description: 'Optional payload of event'
Define acknowledge message to channel
Extend the channel the Heart-Counter
used to include the acknowledge
message.
1channels:
2 root:
3 address: /
4 messages:
5 hello:
6 $ref: '#/components/messages/hello'
7 reaction:
8 $ref: '#/components/messages/reaction'
9 acknowledge:
10 $ref: '#/components/messages/acknowledge'
Define operations
Now you've reached the most important part of the tutorial; it's time to represent the Request/Reply pattern.
Both helloListener
and reactionListener
operations are set to receive
events. However, in the case of reactionListener
, you also want to represent the message sent back to the server. This is where the reply
attribute comes into play.
Since both the request and reply function happens over the same WebSocket URL, both channel
values stay the same. However, you can differentiate each operation's message by specifying the messages sent or received.
Thus, you can say that for a reaction
message received over the root
channel, the reactionListener
operation will reply with the acknowledge
message over the same channel.
1operations:
2 helloListener:
3 action: receive
4 channel:
5 $ref: '#/channels/root'
6 messages:
7 - $ref: '#/channels/root/messages/hello'
8 reactionListener:
9 action: receive
10 channel:
11 $ref: '#/channels/root'
12 messages:
13 - $ref: '#/channels/root/messages/reaction'
14 reply:
15 messages:
16 - $ref: '#/channels/root/messages/acknowledge'
17 channel:
18 $ref: '#/channels/root'
Putting all this together, you have your AsyncAPI document ready to go!
1asyncapi: 3.0.0
2info:
3 title: Implement Request/Reply in an AsyncAPI document for a Slack app
4 version: 1.0.0
5 description: >
6 The Heart-Counter manages popular messages in a Slack workspace by
7 monitoring message reaction data. It also sends an acknowledgment message
8 back to the Slack Server to indicate it has received the message.
9servers:
10 production:
11 host: wss-primary.slack.com
12 pathname: /link
13 protocol: wss
14 description: Slack's server in Socket Mode for real-time communication
15channels:
16 root:
17 address: /
18 messages:
19 hello:
20 $ref: '#/components/messages/hello'
21 reaction:
22 $ref: '#/components/messages/reaction'
23 acknowledge:
24 $ref: '#/components/messages/acknowledge'
25 bindings:
26 ws:
27 query:
28 type: object
29 description: >-
30 Tokens are produced in the WebSocket URL generated from the
31 [apps.connections.open](https://api.slack.com/methods/apps.connections.open)
32 method from Slack's API
33 properties:
34 ticket:
35 type: string
36 description: Temporary token generated when connection is initiated
37 const: 13748dac-b866-4ea7-b98e-4fb7895c0a7f
38 app_id:
39 type: string
40 description: Unique identifier assigned to the Slack app
41 const: fe684dfa62159c6ac646beeac31c8f4ef415e4f39c626c2dbd1530e3a690892f
42operations:
43 helloListener:
44 action: receive
45 channel:
46 $ref: '#/channels/root'
47 messages:
48 - $ref: '#/channels/root/messages/hello'
49 reactionListener:
50 action: receive
51 channel:
52 $ref: '#/channels/root'
53 messages:
54 - $ref: '#/channels/root/messages/reaction'
55 reply:
56 messages:
57 - $ref: '#/channels/root/messages/acknowledge'
58 channel:
59 $ref: '#/channels/root'
60components:
61 messages:
62 reaction:
63 summary: Action triggered when the channel receives a new reaction-added event
64 payload:
65 $ref: '#/components/schemas/reaction'
66 hello:
67 summary: Action triggered when a successful WebSocket connection is established
68 payload:
69 $ref: '#/components/schemas/hello'
70 acknowledge:
71 summary: Acknowledgement response sent to Server
72 payload:
73 $ref: '#/components/schemas/acknowledge'
74 schemas:
75 hello:
76 type: object
77 properties:
78 type:
79 type: string
80 description: A hello string confirming WebSocket connection
81 connection_info:
82 type: object
83 properties:
84 app_id:
85 type: string
86 num_connections:
87 type: integer
88 debug_info:
89 type: object
90 properties:
91 host:
92 type: string
93 started:
94 type: string
95 build_number:
96 type: integer
97 approximate_connection_time:
98 type: integer
99 reaction:
100 type: object
101 properties:
102 envelope_id:
103 type: string
104 description: 'Unique ID assigned to payload'
105 payload:
106 type: object
107 description: 'Payload of the reaction added event'
108 properties:
109 token:
110 type: string
111 team_id:
112 type: string
113 event:
114 type: object
115 properties:
116 user:
117 type: string
118 description: User ID who performed this event
119 reaction:
120 type: string
121 description: The only reaction that you need is a heart emoji
122 item_user:
123 type: string
124 description: |
125 User ID that created the original item that has been reacted
126 to
127 item:
128 type: object
129 properties:
130 channel:
131 type: string
132 description: Channel information of original message
133 ts:
134 type: string
135 description: Timestamp information of original message
136 event_ts:
137 type: string
138 description: Reaction timestamp
139 type:
140 type: string
141 accepts_response_payload:
142 type: boolean
143 acknowledge:
144 type: object
145 properties:
146 envelope_id:
147 type: string
148 description: 'Unique ID of acknowledged payload'
149 payload:
150 type: object
151 description: 'Optional payload of event'
Summary
Great job getting to the end! In this tutorial, you learned how to create an AsyncAPI document for a use case that implemented the Request-Reply messaging pattern. Now, you can explore this pattern with sub-patterns to see how it works with real-life use cases.