amplify-android
amplify-android copied to clipboard
[API] Subscribe with arguments (real time filtering)
There should be a way to pass arguments to subscriptions so that only a subset is subscribed.
Model schema -
type MyData @model {
id: ID!
x: Int
other_data: String
}
Subscription method onUpdateMyData
which take an input parameter x
-
type Subscription {
onUpdateMyData(x: Int): MyData
@aws_subscribe(mutations: ["updateMyData"])
}
Mutation method updateMyData
-
type Mutation {
updateMyData(input: UpdateMyDataInput!, condition: ModelMyDataConditionInput): MyData
}
Following the official documentation, I wrote the below code for subscription. Works as expected, i.e, gets triggered whenever the updateMyData
mutation is called, irrespective of the value of x.
Amplify.API.subscribe(ModelSubscription.onUpdate(MyData::class.java),
{ Log.i("ApiQuickStart", "Subscription established") },
fun(onUpdate: GraphQLResponse<MyData>) {
if (onUpdate.hasData()) {
Log.i("ApiQuickStart", "Update: " + onUpdate.data.toString())
} else if (onUpdate.hasErrors()) {
Log.e("ApiQuickStart", "Error: " + onUpdate.errors.joinToString { it.message })
} else {
Log.i("ApiQuickStart", "Null update")
}
},
{ onFailure -> Log.e("ApiQuickStart", "Subscription failed", onFailure) },
{ Log.i("ApiQuickStart", "Subscription completed") }
)
But the problem is, I only want to subscribe for a specific value of x, say 5. So, I tried by modifying the request -
ModelSubscription.onUpdate(MyData::class.java).apply {
putVariable("x", 5)
}
This made no difference. I'm still receiving updates for other values of x.
This is how I call updateMyData
mutation from AppSync console -
mutation {
updateMyData( input: {
id: 1,
x: 5,
other_data: "some updated info"
} ) {
id, x, other_data
}
}
Subscription in AppSync console works like a charm, i.e, it gets triggered only for a subset where x = 5
-
subscription {
onUpdateMyData(x: 5) {
id, x, other_data
}
}
Just to mention, DynamoDB is used as the data source.
@chiragmittal19
We could add a filtering argument to ModelSubscription.onUpdate(...)
, like:
public static <M extends Model> GraphQLRequest<M> onUpdate(
Class<M> modelType, QueryPredicate filter) {
...
}
Is this what you have in mind?
This would constrain the set of results returned over the network, by means of a GraphQL predicate.
Since we don't have that, for the time-being, you could do the filtering on the client. I recommend using the Rx Bindings for this.
RxAmplify.API.subscribe(onUpdate(MyData::class.java))
.filter { post -> !post.hasErrors() && post.hasData() }
.map { post -> post.data }
.filter { data -> data.x == "5" }
.subscribe(
{ Log.i("Demo", "Found a match: $it") },
{ Log.i("Demo", "No matches.", it) }
)
A QueryPredicate
sounds good. But in terms of performance and cost, will that be equivalent to passing an argument to the subscription method?
I guess it would be better to have an option to pass the complete string, maybe like this -
String subscriptionString =
```subscription {
onUpdateMyData(x: 5) {
id, x, other_data
}
}```
Amplify.API.subscribe(subscriptionString,
{ Log.i("ApiQuickStart", "Subscription established") },
fun(onUpdate: GraphQLResponse<MyData>) {
if (onUpdate.hasData()) {
Log.i("ApiQuickStart", "Update: " + onUpdate.data.toString())
} else if (onUpdate.hasErrors()) {
Log.e("ApiQuickStart", "Error: " + onUpdate.errors.joinToString { it.message })
} else {
Log.i("ApiQuickStart", "Null update")
}
},
{ onFailure -> Log.e("ApiQuickStart", "Subscription failed", onFailure) },
{ Log.i("ApiQuickStart", "Subscription completed") }
)
@chiragmittal19 Thanks for the feedback! We prioritize work based on the number of reactions an issue receives. I'll close this issue for now, but let's leave it as a feature request.
If you are reading this and would like to see this feature implemented, please add a 👍 here: https://github.com/aws-amplify/amplify-android/issues/580#issue-639443740
Yes would like this feature. Very helpful to reduce network traffic
I also want this feature. Maybe this feature makes more secure in addition to moderating network traffic.
For anyone who finds themselves here... AppSync has a feature that MIGHT help you like it helped me
https://docs.aws.amazon.com/appsync/latest/devguide/extensions.html
$extensions.setSubscriptionFilter
It allows you to add additional filters on the server side
@jamesonwilliams Any update on the feature Request?
Hey, @vibhorkhurana580 - sorry, I haven't worked on this project in a number of years. Overall I'd encourage folks to migrate to Apollo Kotlin, which also supports AppSync's flavor of WebSockets if you're stuck on that backend for now.