aws-mobile-appsync-sdk-js
aws-mobile-appsync-sdk-js copied to clipboard
Subscription confirmation
Do you want to request a feature or report a bug? feature
What is the current behavior?
client.subscribe(query: ...)
call does not provide a way to wait for the start_ack
message, there is no way of knowing when the subscription is actually active.
My use case is this: Client A can initiate an operation that might cause Client B to perform certain mutations asynchronously on an AppSync API. Client A would like to get notified of these mutations, thus a subscription is created before initiating the connection.
Order of operations is thus:
- client a subscribes to client b events (through subscription)
- client a initiates operation
- client b performs mutations
- client a receives events from graphql subscription
Because there is no way of knowing when the subscription in 1. is active, client b might have performed the mutation before client a's subscription was active.
As a temporary workaround, I have added a sleep
before initiating the operation, which is, of course, not ideal.
Is there a way to receive AppSync's start_ack
message as a user?
Any updates on this?
Hope this helps
/**
* Assumptions that the example code makes:
* 1. You are using the Apollo client v3 way of setup
* 2. You are calling the apolloClient.subscribe way of subscription instead of React components way
* 3. aws-appsync-subscription-link version - 3.1.2
*/
import { createSubscriptionHandshakeLink } from 'aws-appsync-subscription-link'
// Your remaining imports
const link = ApolloLink.from([
setContext(() => {
return {
controlMessages: {
'@@controlEvents': true //This enables aws-appsync-subscription-link to send the control messages such as start_ack
},
}
}),
createSubscriptionHandshakeLink(/* params here */),
// Your other links here
])
const client = new ApolloClient({
link
})
async function subscribe(query, variables) {
const handler = await client.subscribe({
query,
variables
});
return new Promise(resolve => {
handler.subscribe({
next: async (event) => {
if(event.extensions.controlMsgType == 'CONNECTED') {
//This means start_ack signal has come
resolve(true)
return true
}
//Handle other events here
},
error: (error) => {
// Resolve with error here so client can handle the error
resolve(false)
},
})
})
}
const subscriptionSuccessful = await subscribe('Your subscription query here', { 'You variables': 'here' })
if(subscriptionSuccessful) {
//Continue with your code
}
/**
* Note:
* 1. I've not handled all the cases. Please go through the references to handle the connection error cases also to avoid the Promise being held up forever.
* You could also implement a timeout
*
* References:
* 1. Code that handles sending this event: https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/8aa3884309720be9b01edf6042f36ae5ff4368e7/packages/aws-appsync-subscription-link/src/realtime-subscription-handshake-link.ts#L169
* 2. Code that takes the context we are passing that enables above condition: https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/8aa3884309720be9b01edf6042f36ae5ff4368e7/packages/aws-appsync-subscription-link/src/realtime-subscription-handshake-link.ts#L104
* 3. Code where this event (start_ack) comes: https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/8aa3884309720be9b01edf6042f36ae5ff4368e7/packages/aws-appsync-subscription-link/src/realtime-subscription-handshake-link.ts#L706
* 4. Doc that explains subscription flow: https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html
*/