Amplify DataStore Not Syncing Deleted Records on iOS
rohit3d2003 opened this issue · 8 comments
Describe the bug
I am experiencing an issue with Amplify DataStore in my iOS app. When I delete a record directly from DynamoDB using a GraphQL API call via Lambda function, the data is successfully deleted from DynamoDB. However, this deletion is not reflected in the iOS app or Amplify Studio -> Content section.
Steps To Reproduce
1. Use a GraphQL API call to delete a record from DynamoDB.
2. Observe that the record is deleted in DynamoDB, but it still appears in the iOS app.
3. Check the record in Amplify Studio -> Content; the record still appears there as well.
4. There are no errors in the Xcode console or Amplify Studio -> Content section.
5. If the app is deleted and reinstalled, the previously deleted record no longer appears in the app.
Expected behavior
The iOS app and Amplify Studio -> Content section should automatically sync and reflect the deletion of the record from DynamoDB.
Amplify Framework Version
2.36
Amplify Categories
API, DataStore
Dependency manager
Swift PM
Swift version
5.10
CLI version
12.12.4
Xcode version
15.4
Relevant log output
No response
Is this a regression?
Yes
Regression additional context
No response
Platforms
iOS
OS Version
17.5
Device
iPhone 15
Specific to simulators
No response
Additional context
• I have set Time to Live (TTL) on the DynamoDB table to 1 minute.
• I’ve noticed that if the iOS app is open when the deletion(soft) occurs (triggered by a Lambda function), the app syncs the deletion properly.
• However, if the record is physically deleted from DynamoDB while the app is not running, the sync does not happen when the app is reopened.
• This is more of an observation and hasn’t been thoroughly tested, but it might be relevant to the issue.
No response
Hi @rohit3d2003, GraphQL mutations selection set need to match the selection set of the Subscription operation that is established by Swift DataStore or Amplify Studio. The corresponding mutation response as a subscription event on the clients have to be decoded to each respective platform's types. It needs all the fields of the model, the system metadata fields like _version
, and the nested foreign key field's identifier fields. To help you debug this further, can you provide us with
- the schema you are using for your data modeling use cases.
- the GraphQL request you can sending via the Lambda call.
- verify that the clients are receiving the mutation response and attempts to decode the data. This can be seen with the app running,
DataStore.start()
called, DataStore started, verbose logging enabled, and viewing the console logs when the mutation is sent.
The selection set controls the about of data the subscription event is sent with, if not aligned, will cause decoding errors.
@lawmicha - Both my selection set for the mutation and subscription operations are the same. As mentioned earlier, I tried deleting a transaction from Lambda while the iOS app was running in the Simulator. In this scenario, the iOS app received the delete event and synced properly. However, the issue occurs when a transaction is deleted via Lambda (e.g., overnight when my app isn’t running in the Simulator or on a physical device). The transaction is successfully deleted from DynamoDB, but Amplify Studio -> Content still shows the transaction, and it never syncs with the iOS app. I have baseTableTtl set to 1 on all tables via override, but I’m not sure if this is affecting the sync behavior in this scenario.
Below is the requested items
Base Table TTL
resources.models["Transaction"].modelDatasource.dynamoDbConfig['deltaSyncConfig']['baseTableTtl'] = '1';
Schema
type Transaction @model
@auth(rules: [
{ allow: owner, operations: [create, read, update, delete] },
{ allow: groups, groups: ["Admin"], operations: [create, read, delete, update] }
]) {
id: ID!
date: AWSDate!
owner: String @auth(rules: [
{ allow: owner, operations: [create, read, delete] },
{ allow: groups, groups: ["Admin"], operations: [create, read, delete] }
])
categorizationRuleTransactionsId: ID @auth(rules: [
{ allow: owner, operations: [create, read, update, delete] },
{ allow: groups, groups: ["Admin"], operations: [create, read, delete, update] }
])
}
type CategorizationRule @model
@auth(rules: [
{ allow: owner, operations: [create, read, update, delete] },
{ allow: groups, groups: ["Admin"], operations: [read, delete, update] }
]) {
id: ID!
category: String!
transactions: [Transaction] @hasMany
owner: String @auth(rules: [
{ allow: owner, operations: [create, read, delete] },
{ allow: groups, groups: ["Admin"], operations: [read, delete] }
])
}
GraphQL Delete Mutation Request
const deleteTransactionMutation = /* GraphQL */ `
mutation deleteTransaction($input: DeleteTransactionInput!) {
deleteTransaction(input: $input) {
_deleted
_lastChangedAt
_version
categorizationRuleTransactionsId
createdAt
date
id
owner
updatedAt
}
}
`;
Hi @rohit3d2003, the app or Amplify Studio will catch up to the changes with the sync query. When you launch the app and start DataStore, are you able to observe that the data that is fetched and reconciled? It should perform syncTransaction
operations. The results in the response is what is reconciled with the local database of each device. If you can capture the verbose logs, you can reply this request in the AppSync console to view which items are in the response.
Could the baseTTL be affecting the response of the sync query such that the item no longer exists so it doesn't get returned on the query, thus not get reconciled?
Hi @lawmicha - It’s been three days now, and syncing still hasn’t caught up. As I mentioned earlier, this issue only occurs when the app wasn’t running at the time the record was deleted from DynamoDB, and since the record no longer exists, it doesn’t reconcile. I’ve increased the TTL to 1 day to see if this changes anything. If it does, app developers will need to ensure the correct TTL is set based on how frequently the app is expected to run. If the duration exceeds the TTL, the datastore should be cleared to allow resyncing.
I believe the TTL defaults set to 30 days and when the item is soft deleted (_deleted = true), sync query will return them during catch up and reconcile the soft deleted items by removing the corresponding item from the local store on the device. If the short TTL is causing the issue, is there a reason to have reduced this from the default?
It's mostly due to cost. I don't need to store the deleted items so removing them earlier saves the storage cost. Btw, increasing the Ttl to 1 day fixed it. I am thinking of going with default of 30 days now.
Closing the ticket as the issue seems to be resolved.
This issue is now closed. Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.