amplify-swift
amplify-swift copied to clipboard
Deleting a parent in datastore doesn't delete the children
Describe the bug
In iOS, when you delete a parent object with a one to many relationship, the children are not removed from the DataStore.
Note that the expected behavior of deleting the children does work outside the iOS context. As an example, when I perform the same delete action in the Amplify Studio Content tab, the children are removed.
Steps To Reproduce
Steps to reproduce the behavior:
1. Setup a schema with a 1:M relationship
extension User {
// MARK: - CodingKeys
public enum CodingKeys: String, ModelKey {
case id
case username
case email
case Tests
case createdAt
case updatedAt
}
public static let keys = CodingKeys.self
// MARK: - ModelSchema
public static let schema = defineSchema { model in
let user = User.keys
model.authRules = [
rule(allow: .private, operations: [.create, .update, .delete, .read])
]
model.pluralName = "Users"
model.fields(
.id(),
.field(user.username, is: .required, ofType: .string),
.field(user.email, is: .optional, ofType: .string),
.hasMany(user.Tests, is: .optional, ofType: Test.self, associatedWith: Test.keys.userID),
.field(user.createdAt, is: .optional, isReadOnly: true, ofType: .dateTime),
.field(user.updatedAt, is: .optional, isReadOnly: true, ofType: .dateTime)
)
}
}
extension Test {
// MARK: - CodingKeys
public enum CodingKeys: String, ModelKey {
case id
case test
case userID
case createdAt
case updatedAt
}
public static let keys = CodingKeys.self
// MARK: - ModelSchema
public static let schema = defineSchema { model in
let test = Test.keys
model.authRules = [
rule(allow: .private, operations: [.create, .update, .delete, .read])
]
model.pluralName = "Tests"
model.attributes(
.index(fields: ["userID"], name: "byUser")
)
model.fields(
.id(),
.field(test.test, is: .optional, ofType: .string),
.field(test.userID, is: .required, ofType: .string),
.field(test.createdAt, is: .optional, isReadOnly: true, ofType: .dateTime),
.field(test.updatedAt, is: .optional, isReadOnly: true, ofType: .dateTime)
)
}
}
2. In iOS, use the method:
Amplify.DataStore.delete(model) { result in
...
}
3. Let datastore perform sync
4. See that parent object is deleted but the children objects remain
Expected behavior
From the Amplify documentation:
When you delete a parent object in a one to many relationship, the children will also be removed from the DataStore and mutations for this deletion will be sent over the network.
Amplify Framework Version
1.27.1
Amplify Categories
DataStore
Dependency manager
Swift PM
Swift version
5.0
CLI version
9.1.0
Xcode version
13.4.1
Relevant log output
<details>
<summary>Log Messages</summary>
INSERT LOG MESSAGES HERE
```
Is this a regression?
No
Regression additional context
I have not tried before
Device
iPhone 13 Pro
iOS Version
15.5
Specific to simulators
No response
Additional context
No response
Sadly enough, I'm also still seeing it.
At this point, I don't have a way to reproduce it, but users have complained about the syncing going bad. I've determined the cause to be exactly that. This starts to be a nightmare to be honest as this has been going on forever.
@depthzadmin can you share your schema so that we can reproduce this on our end as well?
type User @model @auth(rules: [{allow: private}]) {
id: ID!
username: String!
email: String
Tests: [Test] @hasMany(indexName: "byUser", fields: ["id"])
}
type Test @model @auth(rules: [{allow: private}]) {
id: ID!
test: String
userID: ID! @index(name: "byUser")
}
Does the schema I added help you reproduce the problem?
Hi @depthzadmin, thank you for the schema. I believe I have encountered this issue during some my recent testing and the problem occurs when using uni-directional hasMany, without the belongsTo, is failing to retrieve all the Test models when a User is deleted. Cascade delete works by querying for all the Test models by the model being deleted (user's id) and syncing the children models before the parent (sync Test then sync User delete). I believe this is a bug we need to investigate further and see how cascade delete is operating against an unidirectional hasMany and see if there's something that can be done to successfully get the children models. One workaround is to create a bi-directional relationship and add that the Test belongs to User.
Hi @depthzadmin , When you deleting the parent resource, are some of the children get successfully deleted or none of the children are deleted?
We managed to reproduce a similar issue that some of the children become dangling resource as the mutation is not executed correctly. Could you verify whether the fix is also fixing your issue?
I have moved to release 2.11.4. Is the fix included in this release? If so, I will test.
@depthzadmin , I'm happy to know that you've upgraded to v2, and version 2.11.4 has the necessary fix. Can you please confirm whether the problem still persists?
@5d I have tested the change in my app and can confirm that the problem has been resolved. Thank you!
Unfortunately my testing was wrong. I do still see the incorrect behavior of dependent data not getting deleted. I was tricked when testing by looking at the Content in the Amplify Studio project. When the delete first happens the data is removed. However, after refreshing the Amplify Studio page, the dependent data reappears. This is the same as before.
Can this issue be reopened?
Hi @depthzadmin ,
Feel free to reopen it if the data schema and reproduce steps are the same as documented in this issue. Otherwise, please create a new one. Also, could you please attach more information such as verbose log and version?