awslabs / aws-mobile-appsync-sdk-android

Android SDK for AWS AppSync.
https://docs.amplify.aws/sdk/api/graphql/q/platform/android/
Apache License 2.0
105 stars 58 forks source link

Delta sync base query always runs again after process restart #207

Open BenTilbrook opened 5 years ago

BenTilbrook commented 5 years ago

Describe the bug The base query executes regardless of whether the elapsed time exceeds the configured base refresh interval, if the process is restarted. This is because the cache key used is unstable and based on toString().

The specific API in use here is:

com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient#sync(com.apollographql.apollo.api.Query<D,T,V>, com.apollographql.apollo.GraphQLCall.Callback<com.apollographql.apollo.api.Query.Data>, com.apollographql.apollo.api.Subscription<D,T,V>, com.amazonaws.mobileconnectors.appsync.AppSyncSubscriptionCall.Callback, com.apollographql.apollo.api.Query<D,T,V>, com.apollographql.apollo.GraphQLCall.Callback<com.apollographql.apollo.api.Query.Data>, long)

To Reproduce

Expected behavior When running the app for the second time, the delta query is executed because the base refresh interval has not elapsed.

Actual behavior The base query is executed again, because the database key is unstable and will never match the previous process instance.

Environment(please complete the following information):

Device Information (please complete the following information):

Additional context The SQLite database key used to store the last_run_time of a delta sync operation is generated using string concatenation of the queries and subscriptions toString() values, resulting in an unstable value that is unusable between process instances.

Example key:

com.example.appsync.generated.AllEventsQuery@e2e512dcom.example.appsync.generated.OnDeltaEventSubscription@c427662com.example.appsync.generated.AllEventsDeltaQuery@a2a73f3

I would expect the key to be based on the GraphQL query snippets themselves.

BenTilbrook commented 5 years ago

Appears to be a similar issue to #103.

bardyamomeni commented 5 years ago

Same issue here. I think the problem is with the code generator for queries. The generated code implementing the queries does not override the toString() method and always return the object reference. So when the base query executor uses 'getKey()' method, it will generate object reference which changes with every app restart. When can we have a fix for this?

byteamaze commented 4 years ago

Same issue. When to fix it?

jamesonwilliams commented 4 years ago

Thanks all for the report -

I believe I noticed this issue while working on a cleanup of the tests, as well.

https://github.com/awslabs/aws-mobile-appsync-sdk-android/commit/1bb7ef90042f062bdba9ef1f9ee0745ac3589d28#r37062293

Don’t have a fix date for this yet, but this looks high priority.

byteamaze commented 4 years ago

I have fixed it and seems work fine.

Refer to aws-mobile-appsync-sdk-ios, change mehtod "getkey" in com.amazonaws.mobileconnectors.appsync.AWSAppSyncDeltaSync.java

private String getKey( ) {
    return getKey(baseQuery) + getKey(subscription) + getKey(deltaQuery);
}

private String getKey(Operation operation) {
     String key = "";
     if (operation != null) {
        key += operation.getClass().getSimpleName();
        Set<String> keys = operation.variables().valueMap().keySet();
        if (!keys.isEmpty()) {
            List vars = new ArrayList(keys);
            Collections.sort(vars);
            key += vars.toString();
        }
     }
     return key;
}

Hope official fix soon.