aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.41k stars 2.12k forks source link

How do I delete data both locally and on the server of my table, because I deleted on the Server but it's still present locally #11328

Open elkee2003 opened 1 year ago

elkee2003 commented 1 year ago

Which Specific Feature is your question related to?

DataStore

Question

I created a user from VS code to be saved in the Content (Data Manager). When I create this, I can see it both in my android emulator and in my Table in 'Content'. This is the code for creating the User:

import { createContext, useState,useEffect, useContext } from "react";
import {Auth, DataStore} from 'aws-amplify';
import { User } from "../models";

const AuthContext = createContext({})

const AuthContextProvider = ({children})=>{
    const [authUser, setAuthUser] = useState(null)
    const [dbUser, setDbUser] = useState(null) 
    const sub = authUser?.attributes?.sub;

    useEffect(()=>{
        Auth.currentAuthenticatedUser({bypassCache: true}).then(setAuthUser)
    },[]);

    useEffect(()=>{
        DataStore.query(User, (user)=>user.sub.eq(sub)).then((users)=>setDbUser(users[0]))
        console.log(dbUser)
    }, [sub])

    return(
        <AuthContext.Provider value={{authUser, dbUser, sub, setDbUser }}>
            {children}
        </AuthContext.Provider>
    )
}

export default AuthContextProvider;

export const useAuthContext = ()=> useContext(AuthContext)

This is where I input the data, and then it is saved in Content

const ProfileScreen = () => {

  const {dbUser} = useAuthContext()

    const [name, setName] = useState(dbUser?.name || "")
    const [address, setAddress] = useState(dbUser?.address || "")
    const [lat, setLat] = useState("0")
    const [lng, setLng] = useState ("0")    

    const {sub, setDbUser} = useAuthContext()

    const onSave= async()=>{
      try{
             const user = await DataStore.save(new User({
              name, 
              address,
              lat:parseFloat(lat), 
              lng:parseFloat(lng), 
              sub
            })
            );

            console.log(user)
            setDbUser(user)
          }catch(e){
            Alert.alert("Error", e.message)
          }
    }

However if I delete the User in Content in Aws staging data manager, it still shows that the data has not been deleted from my code, because I can still access it. So where can I find the data to be deleted from both my code and Content. Thank you.

Attached are the photos of my Content table and my code This is the photo of my content, you can see there is no user: Screenshot (9)

This is where I query my data, you look at the console you can see it is still querying a user, despite the fact that I refreshed it. Screenshot (11)

This is where I save the user to Content in aws. However, when I save, it saves successfully and I see in my table, but when I delete it from my table using the management content, if doesn't delete successfully because i can still access it Screenshot (10)

ykethan commented 1 year ago

Hey @elkee2003, 👋 thank you for reaching out. Could you open the DynamoDB table associated with the data model user in the AWS console and check if the table has any records?

chrisbonifacio commented 1 year ago

Hi @elkee2003, following up on @ykethan's request.

When deleting records in a DataStore enabled AppSync API, the records are not removed from the server but rather marked for deletion at some point in the future. So you might find that the record exists in DynamoDB but it should have a field like: _deleted: true and a ttl expiration.

In your app, can you check to make sure that DataStore is receiving onUpdate subscription events? You can log the events by adding this line of code where you are configuring Amplify.

Amplify.Logger.LOG_LEVEL = "DEBUG";

Then try deleting a different user and check the console logs for an onUpdate subscription event.

If DataStore receives a record with _deleted: true from a sync or subscription it will then remove it from the local store.

elkee2003 commented 1 year ago

Hey @elkee2003, 👋 thank you for reaching out. Could you open the DynamoDB table associated with the data model user in the AWS console and check if the table has any records?

A screenshot of the table was added in my uploads Screenshot (9)

elkee2003 commented 1 year ago

Hi @elkee2003, following up on @ykethan's request.

When deleting records in a DataStore enabled AppSync API, the records are not removed from the server but rather marked for deletion at some point in the future. So you might find that the record exists in DynamoDB but it should have a field like: _deleted: true and a ttl expiration.

In your app, can you check to make sure that DataStore is receiving onUpdate subscription events? You can log the events by adding this line of code where you are configuring Amplify.

Amplify.Logger.LOG_LEVEL = "DEBUG";

Then try deleting a different user and check the console logs for an onUpdate subscription event.

If DataStore receives a record with _deleted: true from a sync or subscription it will then remove it from the local store.

How do I access DynamoDB to find records?

ykethan commented 1 year ago

hey @elkee2003, we can check this using two options Option 1:

  1. Open AWS console.
  2. search DynamoDB and select tables in the left tab.
  3. search for the User table
  4. then explore items

Option 2:

  1. Open AppSync console in AWS console and select the API created
  2. select data sources in the left tab
  3. click the DynamoDB table associate with User model
  4. then explore items
elkee2003 commented 1 year ago

Hi @elkee2003, following up on @ykethan's request.

When deleting records in a DataStore enabled AppSync API, the records are not removed from the server but rather marked for deletion at some point in the future. So you might find that the record exists in DynamoDB but it should have a field like: _deleted: true and a ttl expiration.

In your app, can you check to make sure that DataStore is receiving onUpdate subscription events? You can log the events by adding this line of code where you are configuring Amplify.

Amplify.Logger.LOG_LEVEL = "DEBUG";

Then try deleting a different user and check the console logs for an onUpdate subscription event.

If DataStore receives a record with _deleted: true from a sync or subscription it will then remove it from the local store.

Yes I found the records still exists and it was on _deleted: true as you presaged. I deleted it from the table on the server. However it is still saved on my locally despite refreshing. How do I get rid of them locally. I am sorry of being a bother, I am quite new to this

chrisbonifacio commented 1 year ago

Yes I found the records still exists and it was on _deleted: true as you presaged. I deleted it from the table on the server. However it is still saved on my locally despite refreshing. How do I get rid of them locally. I am sorry of being a bother, I am quite new to this

@elkee2003 no worries! Unfortunately deleting the record from DynamoDB prevents the client from being able to sync that it was deleted. At this point you would have to delete it from the local store using DataStore.delete or refresh all the data locally by calling DataStore.clear and then restarting DataStore or the app in general to perform a Base Sync which will pull down records from DynamoDB.

elkee2003 commented 1 year ago

Yes I found the records still exists and it was on _deleted: true as you presaged. I deleted it from the table on the server. However it is still saved on my locally despite refreshing. How do I get rid of them locally. I am sorry of being a bother, I am quite new to this

@elkee2003 no worries! Unfortunately deleting the record from DynamoDB prevents the client from being able to sync that it was deleted. At this point you would have to delete it from the local store using DataStore.delete or refresh all the data locally by calling DataStore.clear and then restarting DataStore or the app in general to perform a Base Sync which will pull down records from DynamoDB.

If I do this, surely the event is going to repeat it's self (assuming I don't delete it from DynamoDB in future). How do I delete it from the server which will affect the data locally when I refresh it (so it will be synced)?

elkee2003 commented 1 year ago

Yes I found the records still exists and it was on _deleted: true as you presaged. I deleted it from the table on the server. However it is still saved on my locally despite refreshing. How do I get rid of them locally. I am sorry of being a bother, I am quite new to this

@elkee2003 no worries! Unfortunately deleting the record from DynamoDB prevents the client from being able to sync that it was deleted. At this point you would have to delete it from the local store using DataStore.delete or refresh all the data locally by calling DataStore.clear and then restarting DataStore or the app in general to perform a Base Sync which will pull down records from DynamoDB.

If I do this, surely the event is going to repeat it's self (assuming I don't delete it from DynamoDB in future). How do I delete it from the server which will affect the data locally when I refresh it (so it will be synced)?

Thank you DataStore.delete() worked for me. However the question remains, is there a way I can delete data from the server and it deletes locally? I was watching a tutorial where the developer deleted data from content in Management content and it deleted locally too, because it was synced. If there is no content to draw from then there should be no content locally saved

elkee2003 commented 1 year ago

Hi @elkee2003, following up on @ykethan's request. When deleting records in a DataStore enabled AppSync API, the records are not removed from the server but rather marked for deletion at some point in the future. So you might find that the record exists in DynamoDB but it should have a field like: _deleted: true and a ttl expiration. In your app, can you check to make sure that DataStore is receiving onUpdate subscription events? You can log the events by adding this line of code where you are configuring Amplify.

Amplify.Logger.LOG_LEVEL = "DEBUG";

Then try deleting a different user and check the console logs for an onUpdate subscription event. If DataStore receives a record with _deleted: true from a sync or subscription it will then remove it from the local store.

How do I access DynamoDB to find records?

I ran this Amplify.Logger.LOG_LEVEL = "DEBUG"; and I saw an onUpdateUser which is the model I want to delete from. Please check the photo to see if returned true, because I couldn't see it Screenshot (13)

chrisbonifacio commented 1 year ago

Hi @elkee2003 glad the local delete worked.

Was that onUpdateUser event triggered by deleting the user from the Studio Data manager?

I do see what you mean, there is no _deleted field in the selection set.

If you refresh the app do you still get the user from querying?

elkee2003 commented 1 year ago

Hi @elkee2003 glad the local delete worked.

Was that onUpdateUser event triggered by deleting the user from the Studio Data manager?

I do see what you mean, there is no _deleted field in the selection set.

If you refresh the app do you still get the user from querying?

Yes it was triggered by deleting the user from the studio Data manager. When I refresh the app I still get the user from querying. However I get _deleted field as true on onDeleteUser

elkee2003 commented 1 year ago

Hi @elkee2003 glad the local delete worked. Was that onUpdateUser event triggered by deleting the user from the Studio Data manager? I do see what you mean, there is no _deleted field in the selection set. If you refresh the app do you still get the user from querying?

Yes it was triggered by deleting the user from the studio Data manager. When I refresh the app I still get the user from querying. However I get _deleted field as true on onDeleteUser

I used DataStor.delete() again just to show you where I received _deleted = true onDeleteUser Screenshot focused part (14)

ykethan commented 1 year ago

transferring the issue to the js repository for additional assistance on the datastore behaviours.

svidgen commented 1 year ago

This could be related to querying for the record prior to the sync completing. It's also possible the sync is just failing. Can you check on two things for us?

  1. Are you seeing any ERROR lines in the browser/device log? Or any lines that suggest any models aren't being synced in full?
  2. Can you watch for DataStore's ready event and ensure you're querying after that occurs?

As an side, in lieu of waiting for the ready event, we also provide observe() and observeQuery() methods, which let you watch for creates/updates/deletes as they occur (both locally and as they arrive over the wire). observeQuery in particular will give you snapshots of your query results as records change and move into or out of a result set — effectively giving you an easy way to implement a "live" view of that result set.

elkee2003 commented 1 year ago

This could be related to querying for the record prior to the sync completing. It's also possible the sync is just failing. Can you check on two things for us?

  1. Are you seeing any ERROR lines in the browser/device log? Or any lines that suggest any models aren't being synced in full?
  2. Can you watch for DataStore's ready event and ensure you're querying after that occurs?

As an side, in lieu of waiting for the ready event, we also provide observe() and observeQuery() methods, which let you watch for creates/updates/deletes as they occur (both locally and as they arrive over the wire). observeQuery in particular will give you snapshots of your query results as records change and move into or out of a result set — effectively giving you an easy way to implement a "live" view of that result set.

I can't see any error lines, in the browser/device log. I can see the ready event. However the problem still persists. I took a screenshot of what I received in my console, when I created the user, when I deleted the user and when I updated after deleting the user. Please bear with me, as I can't find my way around this.

On creating the user: Screenshot (24) Screenshot (25) Screenshot (26)

On deleting the user: Screenshot (27) Screenshot (28) Screenshot (29)

On updating my local server after deletion of the user: Screenshot (30) Screenshot (31) Screenshot (32) Screenshot (33) Screenshot (34) Screenshot (35) Screenshot (36) Screenshot (37) Screenshot (38)

Again I am sorry for any stress I may have caused

chrisbonifacio commented 1 year ago

Hi @elkee2003 apologies for the delay. It's a bit unclear to me what the expectation is here. I see the logs where the subscription events are happening on the client side but can you clarify what exactly you are trying to do? It looks like you are creating a user in Studio, deleting it, and then attempting to update it? Is that correct?

If so, what is your use case for updating a user after deletion?

If I'm mistaken, please clarify what the reproduction steps or share the relevant app code for what you're trying to do.

elkee2003 commented 1 year ago

Hi @elkee2003 apologies for the delay. It's a bit unclear to me what the expectation is here. I see the logs where the subscription events are happening on the client side but can you clarify what exactly you are trying to do? It looks like you are creating a user in Studio, deleting it, and then attempting to update it? Is that correct?

If so, what is your use case for updating a user after deletion?

If I'm mistaken, please clarify what the reproduction steps or share the relevant app code for what you're trying to do.

I create a user from my local server and it synchronizes with the remote server (Amplify Studio), in other words I will be able to see the user I created in Amplify studio. However, when I delete a user from Amplify Studio, it does not delete in my local server, in other words, it does not synchronize. I hope this is clear, and it goes without saying, that I truly appreciate your help.

david-mcafee commented 9 months ago

Just unassigned this from me so that this can be picked up for reproduction (cc @chrisbonifacio)