Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AWS Amplify DataStore does not update properly #12916

Open
3 tasks done
koreahn opened this issue Jan 28, 2024 · 10 comments
Open
3 tasks done

AWS Amplify DataStore does not update properly #12916

koreahn opened this issue Jan 28, 2024 · 10 comments
Labels
DataStore Related to DataStore category question General question V5

Comments

@koreahn
Copy link

koreahn commented Jan 28, 2024

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

DataStore

Amplify Version

v5

Amplify Categories

Not applicable

Backend

Amplify CLI

Environment information

# Put output below this line

  System:
    OS: macOS 14.2.1
    CPU: (8) arm64 Apple M1
    Memory: 68.44 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.15.0 - /usr/local/bin/node
    npm: 9.8.1 - /usr/local/bin/npm
    Watchman: 2023.12.04.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 121.0.6167.85
    Safari: 17.2.1
  npmPackages:
    @aws-amplify/rtn-push-notification: ^1.2.3 => 1.2.9 (1.1.9)
    @aws-amplify/ui-react-native: ^1.2.23 => 1.2.29 
    @azure/core-asynciterator-polyfill: ^1.0.2 => 1.0.2 
    @babel/core: ^7.20.0 => 7.23.6 
    @babel/preset-env: ^7.20.0 => 7.23.6 
    @babel/runtime: ^7.20.0 => 7.23.6 
    @lunalee/react-native-raw-bottom-sheet: ^2.2.4 => 2.2.4 
    @react-native-async-storage/async-storage: ^1.19.1 => 1.21.0 
    @react-native-community/netinfo: ^9.4.1 => 9.5.0 
    @react-native-firebase/analytics: ^18.7.3 => 18.7.3 
    @react-native-firebase/app: ^18.7.3 => 18.7.3 
    @react-native-firebase/crashlytics: ^18.7.3 => 18.7.3 
    @react-native/eslint-config: ^0.72.2 => 0.72.2 
    @react-native/metro-config: ^0.72.9 => 0.72.11 
    @react-navigation/material-bottom-tabs: ^6.2.16 => 6.2.19 
    @react-navigation/native: ^6.1.7 => 6.1.9 
    @react-navigation/native-stack: ^6.9.13 => 6.9.17 
    @tsconfig/react-native: ^3.0.0 => 3.0.2 
    @types/react: ^18.0.24 => 18.2.45 
    @types/react-test-renderer: ^18.0.0 => 18.0.7 
    HelloWorld:  0.0.1 
    amazon-cognito-identity-js: ^6.3.1 => 6.3.8 
    amazon-cognito-identity-js/internals:  undefined ()
    aws-amplify: ^5.3.6 => 5.3.13 
    aws-sdk: ^2.1450.0 => 2.1525.0 
    babel-jest: ^29.2.1 => 29.7.0 
    eslint: ^8.19.0 => 8.56.0 
    exampleapp:  0.0.1 
    jest: ^29.2.1 => 29.7.0 
    metro-react-native-babel-preset: 0.76.7 => 0.76.7 (0.76.8)
    prettier: ^2.4.1 => 2.8.8 
    react: 18.2.0 => 18.2.0 
    react-hook-form: ^7.45.4 => 7.49.2 
    react-native: 0.72.3 => 0.72.3 
    react-native-chart-kit: ^6.12.0 => 6.12.0 
    react-native-code-push: ^8.1.0 => 8.1.1 
    react-native-config: ^1.5.1 => 1.5.1 
    react-native-date-picker: ^4.3.3 => 4.3.5 
    react-native-geocoding: ^0.5.0 => 0.5.0 
    react-native-geolocation-service: ^5.3.1 => 5.3.1 
    react-native-get-random-values: ^1.9.0 => 1.10.0 
    react-native-image-picker: ^7.1.0 => 7.1.0 
    react-native-maps: ^1.7.1 => 1.8.4 
    react-native-maps-directions: ^1.9.0 => 1.9.0 
    react-native-modal: ^13.0.1 => 13.0.1 
    react-native-safe-area-context: ^4.7.1 => 4.8.2 
    react-native-screens: ^3.24.0 => 3.29.0 
    react-native-sectioned-multi-select: ^0.10.0 => 0.10.0 
    react-native-select-dropdown: ^3.4.0 => 3.4.0 
    react-native-splash-screen: ^3.3.0 => 3.3.0 
    react-native-svg: ^13.13.0 => 13.14.0 
    react-native-upi-payment: ^1.0.5 => 1.0.5 
    react-native-url-polyfill: ^2.0.0 => 2.0.0 (1.3.0)
    react-native-vector-icons: ^10.0.0 => 10.0.3 
    react-test-renderer: 18.2.0 => 18.2.0 
    stream: ^0.0.2 => 0.0.2 
    typescript: 4.8.4 => 4.8.4 
  npmGlobalPackages:
    @aws-amplify/cli: 12.8.2
    appcenter-cli: 2.14.0
    corepack: 0.15.3
    create-expo-app: 2.0.3
    create-react-native-app: 3.8.0
    eas-cli: 3.12.1
    expo-cli: 6.3.10
    npm: 9.8.1

Describe the bug

I want to save the user token to DB(DynamoDB), so I checked and saved in App.js.
During testing, I noticed that the token often doesn't update. So I tested the token alternately to two different simulators.

Belows are my code.

  useEffect(() => {
    const updateDeviceToken = async () => {
      console.log('Entering updateDeviceToken');
      if (deviceToken) {
        console.log('deviceToken is present');
        if (dbUser && deviceToken) {
          if (dbUser && dbUser.token !== deviceToken) {
            console.log('auth', deviceToken);
            console.log('dbUser.token', dbUser.token);
            console.log('dbUser.id', dbUser.id);

            try {
              const newUser = await DataStore.query(User, user =>
                user.id.eq(dbUser.id),
              );
              console.log('user1', newUser[0]);

              const dbuser = await DataStore.save(
                User.copyOf(newUser[0], updated => {
                  updated.token = deviceToken;
                }),
              );
              console.log('user2', dbuser);
              setDbUser(dbuser);
            } catch (err) {
              console.err('update token error', err);
            }
          }
        } else {
          console.log('dbUser.token is the same as deviceToken');
        }
      } else {
        console.log('deviceToken is not present');
      }
    }

  updateDeviceToken();
}

Belows are logs.

LOG Entering updateDeviceToken
LOG deviceToken is present
LOG auth tokenaaaaa <<<<<<<<<< phisical device token.
LOG dbUser.token tokenbbbbb <<<<<<<<<< saved token in DynamoDB earlier
LOG dbUser.id 73e114d0-6c73-40d0-9b18-c015ae9edd8d
LOG user1 {....."token": "tokenbbbbb",.....}
LOG user2 {....."token": "tokenaaaaa",.....}

On the log, the update appears to be normal. But when I check the actual data on the amplify console, it doesn't update and still shows 'tokenbbbbb'.

And sometimes there is also a problem with the 'User' table query. The 'User' table has not updated token to tokenbbbbb, but when I run the program again and query the 'User' table, it is inquired to tokenbbbbbbbb. (Actual DB shows tokenaaaa in Amplify console).

Several tables have been created and are being used, but this problem only occurs in the 'User' table.

Expected behavior

The token of the physical device shall be updated to DynamoDB

Reproduction steps

  1. Install the react-native app on two physical devices
  2. Log in to the first device and update the token in the User Table
  3. Log in as the second device and update the token in the User table again

Code Snippet

// Put your code below this line.
  useEffect(() => {
    const updateDeviceToken = async () => {
      console.log('Entering updateDeviceToken');
      if (deviceToken) {
        console.log('deviceToken is present');
        if (dbUser && deviceToken) {
          if (dbUser && dbUser.token !== deviceToken) {
            console.log('auth', deviceToken);
            console.log('dbUser.token', dbUser.token);
            console.log('dbUser.id', dbUser.id);

            try {
              const newUser = await DataStore.query(User, user =>
                user.id.eq(dbUser.id),
              );
              console.log('user1', newUser[0]);

              const dbuser = await DataStore.save(
                User.copyOf(newUser[0], updated => {
                  updated.token = deviceToken;
                }),
              );
              console.log('user2', dbuser);
              setDbUser(dbuser);
            } catch (err) {
              console.err('update token error', err);
            }
          }
        } else {
          console.log('dbUser.token is the same as deviceToken');
        }
      } else {
        console.log('deviceToken is not present');
      }
    }

  updateDeviceToken();
}

Log output

// Put your logs below this line

 LOG  Entering updateDeviceToken
 LOG  deviceToken is present
 LOG  auth tokenaaaaa <<<<<<<<<< phisical device token.
 LOG  dbUser.token tokenbbbbb <<<<<<<<<< saved token in DynamoDB earlier
 LOG  dbUser.id 73e114d0-6c73-40d0-9b18-c015ae9edd8d
 LOG  user1 {....."token": "tokenbbbbb",.....}
 LOG  user2 {....."token": "tokenaaaaa",.....}

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

@koreahn koreahn added the pending-triage Issue is pending triage label Jan 28, 2024
@nadetastic nadetastic added the DataStore Related to DataStore category label Jan 28, 2024
@cwomack cwomack self-assigned this Jan 29, 2024
@cwomack cwomack added the V5 label Jan 29, 2024
@cwomack
Copy link
Member

cwomack commented Feb 1, 2024

Hello, @koreahn and sorry to hear you're experiencing this. Have a couple of questions and requests to see if we can help unblock you.

It looks like you're using v5.X of Amplify, so are you able to add logging to your app via the Console Logger? This will allow us to turn the logging level to debug and get a little more information about what's happening with the network requests when attempting to make that update. Looking to see if there's an error from the AppSync side that would give more details about why it's having trouble resolving on the backend. Using the Hub events emitted for DataStore may help as well to isolate this.

Outside of this, can you clarify if you are using auto-merge or OCC for conflict resolution? Thanks!

@koreahn
Copy link
Author

koreahn commented Feb 6, 2024

Hello, @koreahn and sorry to hear you're experiencing this. Have a couple of questions and requests to see if we can help unblock you.

It looks like you're using v5.X of Amplify, so are you able to add logging to your app via the Console Logger? This will allow us to turn the logging level to debug and get a little more information about what's happening with the network requests when attempting to make that update. Looking to see if there's an error from the AppSync side that would give more details about why it's having trouble resolving on the backend. Using the Hub events emitted for DataStore may help as well to isolate this.

Outside of this, can you clarify if you are using auto-merge or OCC for conflict resolution? Thanks!

Hello. Thank you for your reply.
I added logging like below.

import {Logger} from 'aws-amplify';
import {Hub} from 'aws-amplify';
...
const logger = new Logger('AuthContext');
...
...
const listener = Hub.listen('datastore', async hubData => {
    const {event, data} = hubData.payload;
    if (event === 'networkStatus') {
      console.log(`User has a network connection: ${data.active}`);
    }
  });
...
...
const updateDeviceToken = async () => {
      console.log('Entering updateDeviceToken');
      logger.debug('Entering updateDeviceToken');
      if (deviceToken) {
        console.log('deviceToken is present');
        logger.debug('deviceToken is present');
        if (dbUser && deviceToken) {
          if (dbUser && dbUser.token !== deviceToken) {
            console.log('auth', deviceToken);
            logger.debug('auth', deviceToken);
            console.log('dbUser.token', dbUser.token);
            logger.debug('dbUser.token', dbUser.token);
            console.log('dbUser.id', dbUser.id);
            logger.debug('dbUser.id', dbUser.id);

            try {
              const newUser = await DataStore.query(User, user =>
                user.id.eq(dbUser.id),
              );
              console.log('user1', newUser[0]);
              logger.debug('user1', newUser[0]);

              const dbuser = await DataStore.save(
                User.copyOf(newUser[0], updated => {
                  updated.token = deviceToken;
                }),
              );
              console.log('user2', dbuser);
              logger.debug('user2', dbuser);
              setDbUser(dbuser);
            } catch (err) {
              console.err('update token error', err);
              logger.error('update token error', err);
            }
          }
        } else {
          console.log('dbUser.token is the same as deviceToken');
          logger.debug('dbUser.token is the same as deviceToken');
        }
      } else {
        console.log('deviceToken is not present');
        logger.debug('deviceToken is not present');
      }
    };

Belows are the logs. It's same as before. And the log of the catch clause was not printed.

LOG  User has a network connection: true
LOG  User has a network connection: true
LOG  Entering updateDeviceToken
LOG  deviceToken is present
LOG auth tokenaaaaa <<<<<<<<<< phisical device token.
LOG dbUser.token tokenbbbbb <<<<<<<<<< saved token in DynamoDB earlier
LOG dbUser.id 73e114d0-6c73-40d0-9b18-c015ae9edd8d
LOG user1 {....."token": "tokenbbbbb",.....}
LOG user2 {....."token": "tokenaaaaa",.....}

I am very new to using Amplify. Did I apply the logs properly?
And I don't know what auto-merge and OCC are. Can you tell me how to check them?

Let me know if you need anything else.
Thank you.

@chrisbonifacio
Copy link
Member

chrisbonifacio commented Feb 6, 2024

Hi @koreahn, Auto Merge and OCC (Optimistic Concurrency) are conflict resolution strategies you can use with DataStore enabled.

For more info on how they work and differ in behavior please refer to the AppSync documentation:

https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html#conflict-detection-and-resolution

I think what @cwomack was referring to is adding this to your app where you are configuring Amplify.

Amplify.Logger.LOG_LEVEL = 'DEBUG'

This will log all of the Amplify events for all categories

@koreahn
Copy link
Author

koreahn commented Feb 7, 2024

Thank you @chrisbonifacio.

@cwomack
I am not using auto-merge or OCC. Is this the cause of my problem?

@koreahn
Copy link
Author

koreahn commented Feb 12, 2024

Hi @koreahn, Auto Merge and OCC (Optimistic Concurrency) are conflict resolution strategies you can use with DataStore enabled.

For more info on how they work and differ in behavior please refer to the AppSync documentation:

https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html#conflict-detection-and-resolution

I think what @cwomack was referring to is adding this to your app where you are configuring Amplify.

Amplify.Logger.LOG_LEVEL = 'DEBUG'

This will log all of the Amplify events for all categories

Can you help me? What should I do?

@chrisbonifacio
Copy link
Member

@koreahn what conflict resolution strategy are you using? Custom Lambda?

@nadetastic
Copy link
Member

Hi @koreahn following up here - have you had a chance to see the comment from @chrisbonifacio above?

@koreahn
Copy link
Author

koreahn commented Feb 21, 2024

Hello @chrisbonifacio, @nadetastic.

I am very new to Amplify, so I don't know what the conflict resolution strategy is.
I am solely using the DataStore object, nothing else.

How can I check it?

@cwomack cwomack added question General question and removed pending-triage Issue is pending triage labels Mar 4, 2024
@cwomack
Copy link
Member

cwomack commented Mar 5, 2024

Thanks for the replies on this, @koreahn. It sounds like you could be using AutoMerge as the default conflict resolution strategy if you haven't made any changes yourself.

Could you share your schema and possibly the code that's running queries of the object for the second device? Also, are you using the SQLite adapter? Any further reproduction steps or clarity on differences for each device (i.e. code they are running, if they are being opened at same time, etc.) would be helpful as well! Thanks.

@koreahn
Copy link
Author

koreahn commented Mar 7, 2024

Thank you very much @cwomack.

I have not made any changes.
below is my scheme of User table.

type EagerUser = {
  readonly [__modelMeta__]: {
    identifier: ManagedIdentifier<User, 'id'>;
    readOnlyFields: 'createdAt' | 'updatedAt';
  };
  readonly id: string;
  readonly sub?: string | null;
  readonly phoneNumber: string;
  readonly userName?: string | null;
  readonly email?: string | null;
  readonly role?: string | null;
  readonly token?: string | null;
  readonly subRole?: SubRole | keyof typeof SubRole | null;
  readonly createdId?: string | null;
  readonly createdName?: string | null;
  readonly updatedId?: string | null;
  readonly updatedName?: string | null;
  readonly createdAt?: string | null;
  readonly updatedAt?: string | null;
}

type LazyUser = {
  readonly [__modelMeta__]: {
    identifier: ManagedIdentifier<User, 'id'>;
    readOnlyFields: 'createdAt' | 'updatedAt';
  };
  readonly id: string;
  readonly sub?: string | null;
  readonly phoneNumber: string;
  readonly userName?: string | null;
  readonly email?: string | null;
  readonly role?: string | null;
  readonly token?: string | null;
  readonly subRole?: SubRole | keyof typeof SubRole | null;
  readonly createdId?: string | null;
  readonly createdName?: string | null;
  readonly updatedId?: string | null;
  readonly updatedName?: string | null;
  readonly createdAt?: string | null;
  readonly updatedAt?: string | null;
}

export declare type User = LazyLoading extends LazyLoadingDisabled ? EagerUser : LazyUser

export declare const User: (new (init: ModelInit<User>) => User) & {
  copyOf(source: User, mutator: (draft: MutableModel<User>) => MutableModel<User> | void): User;
}

And below is query of the object.

await DataStore.query(User, user =>
        user.sub.eq(authUser?.attributes?.sub),
      )
        .then(users => {
          setDbUser(users[0]);
        })
        .catch(e => {
          console.error(e);
          setDbUser(null);
        });

I dont use SQLite adapter.

I have conducted tests using multiple versions of iOS and Android simulators, as well as physical Android devices. However, I have encountered inconsistency in updates, experiencing cases where updates occur on the same device while other times they do not. I haven't been able to identify any specific rules governing this behavior.

I am not sure if I am answering correctly or not. If these are not correct answer, could you provide more specific details about what tasks I can handle please?

@chrisbonifacio chrisbonifacio removed their assignment May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DataStore Related to DataStore category question General question V5
Projects
None yet
Development

No branches or pull requests

4 participants