We can use the Subscriptions feature with AWS Amplify.
It's easy for us to get started, but it can be complicated.
Previous article, I show Open Chat
.
In this article, I'll show you Multi-Room Chat
sample.
And, there are two way implementations, one is "Easy" way, and another is "Efficient" way.
My repository:
tacck / sample-amplify-subscriptions
Sample code for this article. https://dev.to/tacck/series/11192
TOC
Section | Title |
---|---|
2.1 | Implementations for "Easy" way |
2.2 | Implementations for "Efficient" way |
2.1 Implementations for "Easy" way
Edit GraphQL scheme file
Add a type for Multi-Room Chat.
amplify/backend/api/sampleamplifysubscri/schema.graphql
type RoomChat @model {
id: ID!
roomName: String!
message: String!
}
And, push project.
$ amplify push
Initializing new Amplify CLI version...
Done initializing new version.
Scanning for plugins...
Plugin scan successful
✔ Successfully pulled backend environment dev from the cloud.
Current Environment: dev
| Category | Resource name | Operation | Provider plugin |
| -------- | -------------------- | --------- | ----------------- |
| Api | sampleamplifysubscri | Update | awscloudformation |
? Are you sure you want to continue? Yes
The following types do not have '@auth' enabled. Consider using @auth with @model
- OpenChat
- RoomChat
Learn more about @auth here: https://docs.amplify.aws/cli/graphql-transformer/auth
GraphQL schema compiled successfully.
Edit your schema at /[YOUR_DIRECTORY]/sample-amplify-subscriptions/amplify/backend/api/sampleamplifysubscri/schema.graphql or place .graphql files in a directory at /[YOUR_DIRECTORY]/sample-amplify-subscriptions/amplify/backend/api/sampleamplifysubscri/schema
? Do you want to update code for your updated GraphQL API Yes
? Do you want to generate GraphQL statements (queries, mutations and subscription) based on your s
chema types?
This will overwrite your current graphql queries, mutations and subscriptions Yes
⠼ Updating resources in the cloud. This may take a few minutes...
(snip)
✔ Generated GraphQL operations successfully and saved at src/graphql
✔ All resources are updated in the cloud
GraphQL endpoint: https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$
Write Multi-room Open Chat for "Easy" way
<template>
<v-container>
<v-row>
<v-col cols="12">
<v-card>
<v-card-title>Multi-room Open Chat</v-card-title>
<v-card-text
>Anyone can use this chat. All subscriptions are receved, and
received messages are set in the message list for each
room.</v-card-text
>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-text-field
v-model="inputMessage"
label="New Message"
outlined
clearable
append-outer-icon="mdi-send"
@click:append-outer="sendMessage"
></v-text-field>
</v-col>
</v-row>
<v-tabs
v-model="roomName"
background-color="primary"
center-active
centered
dark
>
<v-tab href="#room1">room1</v-tab>
<v-tab href="#room2">room2</v-tab>
</v-tabs>
<v-card flat>
<v-tabs-items v-model="roomName">
<v-tab-item value="room1">
<v-row class="pa-2">
<v-col cols="6">
<ChatList title="Input" :list="messages.room1"></ChatList>
</v-col>
<v-col cols="6">
<ChatList
title="Subscriptions"
:list="subscriptionMessages.room1"
></ChatList>
</v-col>
</v-row>
</v-tab-item>
<v-tab-item value="room2">
<v-row class="pa-2">
<v-col cols="6">
<ChatList title="Input" :list="messages.room2"></ChatList>
</v-col>
<v-col cols="6">
<ChatList
title="Subscriptions"
:list="subscriptionMessages.room2"
></ChatList>
</v-col>
</v-row>
</v-tab-item>
</v-tabs-items>
</v-card>
</v-container>
</template>
<script>
import { API, graphqlOperation } from 'aws-amplify'
import { createRoomChat } from '@/graphql/mutations'
import { onCreateRoomChat } from '@/graphql/subscriptions'
import ChatList from '@/components/ChatList'
export default {
components: { ChatList },
data: function() {
return {
roomName: null,
inputMessage: '',
messages: {
room1: [],
room2: [],
},
subscriptionMessages: {
room1: [],
room2: [],
},
onCreateOpenChatSubscription: null,
}
},
created: function() {
this.onCreateOpenChatSubscription = API.graphql(
graphqlOperation(onCreateRoomChat),
).subscribe({
next: ({ provider, value }) => {
console.log({ provider, value })
this.subscriptionMessages[value.data.onCreateRoomChat.roomName].push(
value.data.onCreateRoomChat,
)
},
})
},
beforeDestroy: function() {
if (this.onCreateOpenChatSubscription) {
this.onCreateOpenChatSubscription.unsubscribe()
this.onCreateOpenChatSubscription = null
}
},
methods: {
sendMessage: async function() {
const message = await API.graphql(
graphqlOperation(createRoomChat, {
input: { message: this.inputMessage, roomName: this.roomName },
}),
)
console.log(message)
this.messages[this.roomName].push(message.data.createRoomChat)
this.inputMessage = ''
},
},
}
</script>
<style></style>
See other files:
https://github.com/tacck/sample-amplify-subscriptions/tree/2-1-multiroom-chat-filter
The important point is here.
(snip)
created: function() {
this.onCreateOpenChatSubscription = API.graphql(
graphqlOperation(onCreateRoomChat),
).subscribe({
next: ({ provider, value }) => {
console.log({ provider, value })
this.subscriptionMessages[value.data.onCreateRoomChat.roomName].push(
value.data.onCreateRoomChat,
)
},
})
},
(snip)
methods: {
sendMessage: async function() {
const message = await API.graphql(
graphqlOperation(createRoomChat, {
input: { message: this.inputMessage, roomName: this.roomName },
}),
)
console.log(message)
this.messages[this.roomName].push(message.data.createRoomChat)
this.inputMessage = ''
},
},
(snip)
In sendMessage
function, send message with roomName
and set message in this.messages[this.roomName]
list.
In created
function, received message by subscription and set message in this.subscriptionMessages[value.data.onCreateRoomChat.roomName]
list.
It's just filtering by roomName
.
Very Easy way 😃.
However, there is a problem with this way.
We receive messages for "ALL" rooms.
When you see "Room2", you will not want to receive "Room1"'s messages.
Then, We implement for "Efficient" way.
2.2 Implementations for "Efficient" way
Edit GraphQL scheme file
Add a type Subscription.
amplify/backend/api/sampleamplifysubscri/schema.graphql
type Subscription {
onCreateRoomChatByRoomName(roomName: String!): RoomChat
@aws_subscribe(mutations: ["createRoomChat"])
}
This mean: When you use "createRoomChat", the server return data RoomChat
that you created.
You can use onCreateRoomChatByRoomName
instead of onCreateOpenChat
.
And, push project.
$ amplify push
Scanning for plugins...
Plugin scan successful
✔ Successfully pulled backend environment dev from the cloud.
Current Environment: dev
| Category | Resource name | Operation | Provider plugin |
| -------- | -------------------- | --------- | ----------------- |
| Api | sampleamplifysubscri | Update | awscloudformation |
? Are you sure you want to continue? Yes
The following types do not have '@auth' enabled. Consider using @auth with @model
- OpenChat
- RoomChat
Learn more about @auth here: https://docs.amplify.aws/cli/graphql-transformer/auth
GraphQL schema compiled successfully.
Edit your schema at /[YOUR_DIRECTORY]/sample-amplify-subscriptions/amplify/backend/api/sampleamplifysubscri/schema.graphql or place .graphql files in a directory at /[YOUR_DIRECTORY]/sample-amplify-subscriptions/amplify/backend/api/sampleamplifysubscri/schema
? Do you want to update code for your updated GraphQL API Yes
? Do you want to generate GraphQL statements (queries, mutations and subscription) based on your schema types?
This will overwrite your current graphql queries, mutations and subscriptions Yes
⠸ Updating resources in the cloud. This may take a few minutes...
(snip)
✔ Generated GraphQL operations successfully and saved at src/graphql
✔ All resources are updated in the cloud
GraphQL endpoint: https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$
Write Multi-room Open Chat for "Efficient" way
<template>
<v-container>
<v-row>
<v-col cols="12">
<v-card>
<v-card-title>Multi-room Open Chat</v-card-title>
<v-card-text
>Anyone can use this chat. Now, we receive messages only selected
room.
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-text-field
v-model="inputMessage"
label="New Message"
outlined
clearable
append-outer-icon="mdi-send"
@click:append-outer="sendMessage"
></v-text-field>
</v-col>
</v-row>
<v-tabs
v-model="roomName"
background-color="primary"
center-active
centered
dark
>
<v-tab
v-for="(room, index) in rooms"
:key="index"
:href="'#' + room"
@click="setSubscribeByRoomName(room)"
>{{ room }}</v-tab
>
</v-tabs>
<v-card flat>
<v-tabs-items v-model="roomName">
<v-tab-item v-for="(room, index) in rooms" :key="index" :value="room">
<v-row class="pa-2">
<v-col cols="6">
<ChatList title="Input" :list="messages[room]"></ChatList>
</v-col>
<v-col cols="6">
<ChatList
title="Subscriptions"
:list="subscriptionMessages[room]"
></ChatList>
</v-col>
</v-row>
</v-tab-item>
</v-tabs-items>
</v-card>
</v-container>
</template>
<script>
import { API, graphqlOperation } from 'aws-amplify'
import { createRoomChat } from '@/graphql/mutations'
import { onCreateRoomChatByRoomName } from '@/graphql/subscriptions'
import ChatList from '@/components/ChatList'
export default {
components: { ChatList },
data: function() {
return {
roomName: null,
inputMessage: '',
rooms: ['room1', 'room2'],
messages: {
room1: [],
room2: [],
},
subscriptionMessages: {
room1: [],
room2: [],
},
onCreateMultiRoomChatSubscriptions: {
room1: null,
room2: null,
},
}
},
created: function() {
this.setSubscribeByRoomName('room1')
},
beforeDestroy: function() {
this.clearSubscriptions()
},
methods: {
sendMessage: async function() {
const message = await API.graphql(
graphqlOperation(createRoomChat, {
input: { message: this.inputMessage, roomName: this.roomName },
}),
)
console.log(message)
this.messages[this.roomName].push(message.data.createRoomChat)
this.inputMessage = ''
},
setSubscribeByRoomName(roomName) {
this.clearSubscriptions()
this.onCreateMultiRoomChatSubscriptions[roomName] = API.graphql(
graphqlOperation(onCreateRoomChatByRoomName, { roomName: roomName }),
).subscribe({
next: ({ provider, value }) => {
console.log({ provider, value })
this.subscriptionMessages[
value.data.onCreateRoomChatByRoomName.roomName
].push(value.data.onCreateRoomChatByRoomName)
},
})
},
clearSubscriptions() {
this.rooms.forEach(room => {
if (this.onCreateMultiRoomChatSubscriptions[room]) {
this.onCreateMultiRoomChatSubscriptions[room].unsubscribe()
}
this.onCreateMultiRoomChatSubscriptions[room] = null
})
},
},
}
</script>
<style></style>
See other files:
https://github.com/tacck/sample-amplify-subscriptions/tree/2-2-multiroom-chat-subscription
The important point is here.
(snip)
<v-tab
v-for="(room, index) in rooms"
:key="index"
:href="'#' + room"
@click="setSubscribeByRoomName(room)"
>{{ room }}</v-tab
>
(snip)
setSubscribeByRoomName(roomName) {
this.clearSubscriptions()
this.onCreateMultiRoomChatSubscriptions[roomName] = API.graphql(
graphqlOperation(onCreateRoomChatByRoomName, { roomName: roomName }),
).subscribe({
next: ({ provider, value }) => {
console.log({ provider, value })
this.subscriptionMessages[
value.data.onCreateRoomChatByRoomName.roomName
].push(value.data.onCreateRoomChatByRoomName)
},
})
},
(snip)
In setSubscribeByRoomName
function, we use onCreateMultiRoomChatSubscriptions
with roomName
.
Only this change, we receive selected room messages.
Very simple but efficient way.
Next, we see subscriptions with @auth
directive.
Top comments (0)