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

MutationEvent.decodeModel don't decode LazyReference on delete mutation #3252

Closed
gbitaudeau opened this issue Sep 29, 2023 · 7 comments
Closed
Assignees
Labels
bug Something isn't working datastore Issues related to the DataStore category

Comments

@gbitaudeau
Copy link

gbitaudeau commented Sep 29, 2023

Describe the bug

Consider the sample schema (given there : https://docs.amplify.aws/lib/datastore/relational/q/platform/ios/#updated-schema )

enum PostStatus {
  ACTIVE
  INACTIVE
}

type Post @model @auth(rules: [{allow: public}]) {
  id: ID!
  title: String!
  rating: Int!
  status: PostStatus!
  # new field with @hasMany
  comments: [Comment] @hasMany
}

# new model
type Comment @model {
  id: ID!
  content: String
  post: Post @belongsTo
}

I use the LazyReference (using generatemodelsforlazyloadandcustomselectionset option for codegen)

When I use Amplify.DataStore.observe on Comment, if a comment is deleted, the post is not well set on it using MutationEvent.decodeModel, so there is no way to know which post lost a comment.

var postsSubscription:  AmplifyAsyncThrowingSequence<MutationEvent>?

// Then in the body of your code, subscribe to the subscription
func subscribeToPosts() async {
    let commentsSubscription = Amplify.DataStore.observe(Comment.self)
    self. commentsSubscription = commentsSubscription

    do {
        for try await changes in commentsSubscription {
            let comment = try change.decodeModel(as: Comment.self)
            let post = try await comment.post //eror here
        }
    } catch {
        print("Subscription received error: \(error)")
    }
}

Steps To Reproduce

Steps to reproduce the behavior:
1. Setup an env with the previously given code
2. Delete a comment

Expected behavior

The LazyReference must load successfully using let post = try await comment.post

Amplify Framework Version

2.19.0

Amplify Categories

DataStore

Dependency manager

Swift PM

Swift version

5.9

CLI version

12.4.0

Xcode version

15.0

Relevant log output

No response

Is this a regression?

No

Regression additional context

No response

Platforms

iOS

OS Version

iOS 17.0.1

Device

iPhone 14 Pro

Specific to simulators

No response

Additional context

I found a workaround in the generated Comment.init(from decoder: Decoder), I replaced:

_post = try values.decodeIfPresent(LazyReference<Post>.self, forKey: .post) ?? LazyReference(identifiers: nil)

with

_post = try values.fixDecodeLazyReference(type: LazyReference< Post >.self, forKey: . post)

And I added the following extension:

extension KeyedDecodingContainer {
    func fixDecodeLazyReference<T>(type: LazyReference<T>.Type, forKey key: Key) throws -> LazyReference<T> {
        if let identifiers = try? self.decodeIfPresent([LazyReferenceIdentifier].self, forKey: key) {
            return LazyReference(identifiers: identifiers)
        }
        if let result = try self.decodeIfPresent(type, forKey: key) {
            return result
        }
            
        return LazyReference(identifiers: nil)
    }
}
@harsh62 harsh62 added bug Something isn't working datastore Issues related to the DataStore category labels Sep 29, 2023
@harsh62
Copy link
Member

harsh62 commented Sep 29, 2023

Thanks for opening the issue. Our team will look into it and provide an update on the issue.

@harsh62
Copy link
Member

harsh62 commented Jan 19, 2024

Hey @gbitaudeau .. Sorry for the delay. I wanted to ask you further if this is still a problem? I tried this on a latest version of Amplify and everything seems to be working fine.

Adding of the post and comment.

            var post = Post(
                id: "1",
                title: "1",
                status: .draft,
                content: "1")
            let comment = Comment(id: "1", content: "1", post: post)

                try await Amplify.DataStore.save(post)
                try await Amplify.DataStore.save(comment)

Deleting of the comment

                var post = try await Amplify.DataStore.query(Post.self).first!
                try await post.comments!.fetch()
                try await Amplify.DataStore.delete(post.comments!.first!)

Following is my observe query snippet

    // You must hold a reference to your subscription.
    var postsSubscription:  AmplifyAsyncThrowingSequence<MutationEvent>?

    // Then in the body of your code, subscribe to the subscription
    func subscribeToPosts() async {
        let postsSubscription = Amplify.DataStore.observe(Comment.self)
        self.postsSubscription = postsSubscription

        do {
            for try await changes in postsSubscription {
                // handle incoming changes
                if changes.mutationType == "delete" {
                    let comment = try changes.decodeModel(as: Comment.self)
                    let post = try await comment.post
                    print("Subscription received mutation: \(changes)")
                }

            }
        } catch {
            print("Subscription received error: \(error)")
        }
    }

Finally, I don't understand how when decoding a post in the comments with [LazyReferenceIdentifier].self works?

If this is still an issue, would you be able to share the entire code snippet end to end that has the problem so that I can further investigate the issue.

Just FYI, I am using the latest version of Amplify Swift and Amplify CLI.

Thanks.

@harsh62 harsh62 added the pending-community-response Issue is pending response from the issue requestor label Jan 19, 2024
@harsh62 harsh62 self-assigned this Jan 19, 2024
@atierian atierian added the not-reproducible Not able to reproduce the issue label Jan 23, 2024
@gbitaudeau
Copy link
Author

Hi @harsh62 , sorry, I try again on my side and the problem still occurs, but I didn't give you the right steps to reproduce it.

Your code is good.
The problem only occurs when I delete a comment on another device or using this mutation in Amplify studio :

mutation MyMutation {
  deleteComment(input: {id: "XXX", _version: 1}) {
    _deleted
    _lastChangedAt
    _version
    createdAt
    content
    id
    post {
      id
      _deleted
    }
    updatedAt
  }
}

Hope with this you can reproduce it.

@github-actions github-actions bot removed the pending-community-response Issue is pending response from the issue requestor label Jan 29, 2024
@thisisabhash thisisabhash added follow up Requires follow up from maintainers and removed not-reproducible Not able to reproduce the issue labels Feb 6, 2024
@harsh62
Copy link
Member

harsh62 commented Feb 9, 2024

@gbitaudeau I have a potential fix ready that seems to be working correctly for me. Would you be able to validate the fix on my working branch (named: 3252). The PR is also linked to the issue for your reference.

@harsh62 harsh62 removed the follow up Requires follow up from maintainers label Feb 9, 2024
@gbitaudeau
Copy link
Author

Hi @harsh62 tests are ok on my side 👍 on your branch.

@harsh62
Copy link
Member

harsh62 commented Feb 15, 2024

@gbitaudeau A fix for the issue has been released in https://github.com/aws-amplify/amplify-swift/releases/tag/2.26.2. Thanks for your patience.

@harsh62 harsh62 closed this as completed Feb 15, 2024
Copy link
Contributor

⚠️COMMENT VISIBILITY WARNING⚠️

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working datastore Issues related to the DataStore category
Projects
None yet
Development

No branches or pull requests

4 participants