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

Correct way to get ‚_version‘ - field in Amplify Models for updating GraphQL #1614

Closed
rereiusch opened this issue Jan 28, 2022 · 8 comments
Assignees
Labels
api Issues related to the API category bug Something isn't working

Comments

@rereiusch
Copy link

While I can create new Input for my Database using the GraphQL with Amplify API, I cannot update it, the console gives me this Error:

Amplify.GraphQLError(message: "Value for field '$[_version]' must be a number."

I know that Amplify needs a Version because of the enabled conflict detection. When I disable it, it would just work fine, but then Amplify Studio breaks and I cannot edit anything until I reenable it.

I’m trying to provide the version number with following function:

    let user = User(id: "xy", email: "xy", firstName: "xy", lastName: "xy")
    Amplify.API.mutate(request: .updateMutation(of: user, version: 1)) { event in
                switch event {
                case .success(let result):
                    switch result {
                    case .success(let user):
                        print("Successfully updated user: \(user)")
                    case .failure(let error):
                        print("Got failed result with \(error.errorDescription)")
                    }
                case .failure(let error):
                    print("Got failed event with error \(error)")
                        }
                }

The problem is, that if I wanna update a field, I need to provide the correct current version number from the serverside, otherwise the entry won’t get overwritten. So I need to fetch the current version entry for the model I want to update from the database.

And now to the core of my question:

When I check my Schema in the AppSync Console, every models already has the field ‚_version‘. But when I pull the the whole Backend into my App, neither the schema.graphql file contain the field, nor my Amplify Models in Swift get updated. So I cannot fetch the current version and in the aftermath cannot update the entry at all.

What is the right way to fetch the current version? All i could find so far is to just disable the conflict detection #1075, but that’s not the best option for me. Also writing the '_version' field into the Swift model by hand, which actually would work, isn't suitable, as the file gets overwritten every time when the Backend got pulled.

Thank you very much for any help in advance!

Have a great day!

@royjit royjit added api Issues related to the API category pending-triage Issue is pending triage labels Jan 28, 2022
@royjit royjit self-assigned this Jan 28, 2022
@lawmicha
Copy link
Member

lawmicha commented Feb 15, 2022

Hi @rereiusch, when using a conflict resolution enabled API for DataStore, you should use Amplify.DataStore.save to persist the data to local store (will create if does not exist, update if it does). When calling DataStore.save, it will asynchronously and automatically populate the version in the mutation that gets sent to AppSync. Using Amplify.API will directly interact with AppSync will require you to retrieve the version and send that with the update mutation. Before we dive into possible ways to do that, can you explain your use case and why not just call DataStore.save directly?

@lawmicha lawmicha added pending-community-response Issue is pending response from the issue requestor and removed pending-triage Issue is pending triage labels Feb 15, 2022
@lawmicha lawmicha assigned lawmicha and unassigned royjit Feb 15, 2022
@rereiusch
Copy link
Author

Hi @lawmicha, sorry for the late answer. Thank you for your message! I've already tried using Amplify.DataStore.save, as described in the Docs and the Amplify Studio, but when trying to create a new entry, it won't save anything to the Database. Plus I also get the following console output every few seconds after clicking on creating:

Caused by: APIError: Subscription item event failed with error Caused by: GraphQLResponseError<MutationSync<AnyModel>>: GraphQL service returned a successful response containing errors: [Amplify.GraphQLError(message: "Validation error of type FieldUndefined: Field \'_version\' in type \'TryoutModel\' is undefined @ \'onUpdateUserProject/_version\'", locations: nil, path: nil, extensions: nil), Amplify.GraphQLError(message: "Validation error of type FieldUndefined: Field \'_deleted\' in type \'TryoutMode\' is undefined @ \'onUpdate TryoutMode/_deleted\'", locations: nil, path: nil, extensions: nil), Amplify.GraphQLError(message: "Validation error of type FieldUndefined: Field \'_lastChangedAt\' in type \'TryoutMode\' is undefined @ \'onUpdateTryoutMode/_lastChangedAt\'", locations: nil, path: nil, extensions: nil)]

As I read from the console, I still have to provide a _version, even when using DataStore, and then I hit the original problem as I cannot access it through the schema.

Thank you very much!

@lawmicha lawmicha added follow up Requires follow up from maintainers and removed pending-community-response Issue is pending response from the issue requestor labels Feb 25, 2022
@lawmicha
Copy link
Member

lawmicha commented Mar 4, 2022

Hi @rereiusch, were you able to update the backend with or without conflict resolution? Missing fields like "is undefined" for the three conflict resolution fields "_version", "_deleted", "_lastChangedAt" appears that the backend might be set to no conflict resolution enabled. Can you please provide us the schema or any sort of screenshot from your set up? This way we can try it out and see what's going on

@lawmicha lawmicha added pending-community-response Issue is pending response from the issue requestor and removed follow up Requires follow up from maintainers labels Mar 4, 2022
@ameter ameter added the closing soon This issue will be closed in 7 days unless further comments are made. label Mar 11, 2022
@rereiusch
Copy link
Author

rereiusch commented Mar 13, 2022

Hi @lawmicha, I've tried it both ways (conflict solution enabled and disabled) the last few days using Amplify.DataStore.save and none of these worked, unfortunately. When the conflict solution is disabled, I get the console output from my last comment above.

When it's enabled, the following is happening:
When clicking on save, the function returns that the item gets saved. At the same moment, the console gives me the output that subscriptions for every model in my Schema start. After about 100 entries of syncing, this error message occurs for every model (here on Example Project, with isn’t in direct relation to the updated user):

DataStoreError: An error occurred syncing Project Caused by: DataStoreError: failed to process graphqlResponseData Caused by: APIError: failed to process graphqlResponseData Caused by: DataStoreError: The key __typename was not found Recovery suggestion: Check if the parsed JSON contains the expected __typename

Afterward, the console says that it starts unsubscribing from everything again.
In the end, nothing got saved, the User is still the same (even Version) as before the update try. I also checked the __typename of the objects, everyone has the key for it.

About the schema, I've created it with Amplify Studio like the screenshot below (in this case the User - Model, which I tried to update).

Bildschirmfoto 2022-03-11 um 21 44 53

By deploying Amplify created all the mutations and queries, as it should. The final output for the user model in the AppSync Console is the following:

type User @aws_iam
@aws_api_key {
	id: ID!
	email: String!
	firstName: String!
	lastName: String!
	street: String
	postcode: String
	city: String
	profileImage: String
	ProjectsRelationship(
		filter: ModelProjectFilterInput,
		sortDirection: ModelSortDirection,
		limit: Int,
		nextToken: String
	): ModelProjectConnection
	discussions: [OpenDiscussionType]
	professions: [String]
	plattforms: [PlatformType]
	UserXProjectPartitions(
		filter: ModelUserXProjectPartitionFilterInput,
		sortDirection: ModelSortDirection,
		limit: Int,
		nextToken: String
	): ModelUserXProjectPartitionConnection
	projects(
		filter: ModelUserProjectFilterInput,
		sortDirection: ModelSortDirection,
		limit: Int,
		nextToken: String
	): ModelUserProjectConnection
	biography: String
	age: AWSDate
	languages: [String]
	gender: XGender
	createdAt: AWSDateTime!
	updatedAt: AWSDateTime!
}

I hope this helps. If you need anything more, please let me know!

Thank you very much for your help! :)

@lawmicha lawmicha added follow up Requires follow up from maintainers and removed pending-community-response Issue is pending response from the issue requestor closing soon This issue will be closed in 7 days unless further comments are made. labels Mar 14, 2022
@lawmicha lawmicha removed their assignment Mar 25, 2022
@atierian atierian added the bug Something isn't working label Mar 28, 2022
@lawmicha lawmicha added the p2 label Jun 8, 2022
@fudr
Copy link

fudr commented Aug 11, 2022

Hi @lawmicha, I've tried it both ways (conflict solution enabled and disabled) the last few days using Amplify.DataStore.save and none of these worked, unfortunately. When the conflict solution is disabled, I get the console output from my last comment above.

When it's enabled, the following is happening: When clicking on save, the function returns that the item gets saved. At the same moment, the console gives me the output that subscriptions for every model in my Schema start. After about 100 entries of syncing, this error message occurs for every model (here on Example Project, with isn’t in direct relation to the updated user):

DataStoreError: An error occurred syncing Project Caused by: DataStoreError: failed to process graphqlResponseData Caused by: APIError: failed to process graphqlResponseData Caused by: DataStoreError: The key __typename was not found Recovery suggestion: Check if the parsed JSON contains the expected __typename

Afterward, the console says that it starts unsubscribing from everything again. In the end, nothing got saved, the User is still the same (even Version) as before the update try. I also checked the __typename of the objects, everyone has the key for it.

About the schema, I've created it with Amplify Studio like the screenshot below (in this case the User - Model, which I tried to update).

Bildschirmfoto 2022-03-11 um 21 44 53

By deploying Amplify created all the mutations and queries, as it should. The final output for the user model in the AppSync Console is the following:

type User @aws_iam
@aws_api_key {
	id: ID!
	email: String!
	firstName: String!
	lastName: String!
	street: String
	postcode: String
	city: String
	profileImage: String
	ProjectsRelationship(
		filter: ModelProjectFilterInput,
		sortDirection: ModelSortDirection,
		limit: Int,
		nextToken: String
	): ModelProjectConnection
	discussions: [OpenDiscussionType]
	professions: [String]
	plattforms: [PlatformType]
	UserXProjectPartitions(
		filter: ModelUserXProjectPartitionFilterInput,
		sortDirection: ModelSortDirection,
		limit: Int,
		nextToken: String
	): ModelUserXProjectPartitionConnection
	projects(
		filter: ModelUserProjectFilterInput,
		sortDirection: ModelSortDirection,
		limit: Int,
		nextToken: String
	): ModelUserProjectConnection
	biography: String
	age: AWSDate
	languages: [String]
	gender: XGender
	createdAt: AWSDateTime!
	updatedAt: AWSDateTime!
}

I hope this helps. If you need anything more, please let me know!

Thank you very much for your help! :)

I wonder in the subscription is retrieving you the _version as null or the real one from dynamodb?

@lawmicha
Copy link
Member

Thank you for providing a screenshot of the schema you are using. We can use this to verify that the issue is fixed by the changes we have upcoming. I believe this is the same issue as #1753. The selection set sent from Studio is different from the selection set created by the iOS DataStore client, thus iOS client is unable to decode the mutation response successfully. Please track #1753 (comment)

@5d 5d self-assigned this Mar 3, 2023
@royjit royjit unassigned 5d Mar 10, 2023
@royjit
Copy link
Contributor

royjit commented Mar 10, 2023

Changes are released in v2, we are waiting for codegen changes to be released to verify the fix - https://github.com/aws-amplify/amplify-codegen

@royjit
Copy link
Contributor

royjit commented Apr 3, 2023

The feature is released in amplify-swift version 2.6.1 and models generated by amplify-cli version 11.0.3. Before generating models make sure to enable generatemodelsforlazyloadandcustomselectionset to true inside cli.json file.

Here is how my cli.json looks like:

{
  "features": {
    "graphqltransformer": {
      "addmissingownerfields": true,
      "improvepluralization": false,
      "validatetypenamereservedwords": true,
      "useexperimentalpipelinedtransformer": true,
      "enableiterativegsiupdates": true,
      "secondarykeyasgsi": true,
      "skipoverridemutationinputtypes": true,
      "transformerversion": 2,
      "suppressschemamigrationprompt": true,
      "securityenhancementnotification": false,
      "showfieldauthnotification": false,
      "usesubusernamefordefaultidentityclaim": true,
      "usefieldnameforprimarykeyconnectionfield": false,
      "enableautoindexquerynames": true,
      "respectprimarykeyattributesonconnectionfield": true,
      "shoulddeepmergedirectiveconfigdefaults": false,
      "populateownerfieldforstaticgroupauth": true
    },
    "frontend-ios": {
      "enablexcodeintegration": true
    },
    "auth": {
      "enablecaseinsensitivity": true,
      "useinclusiveterminology": true,
      "breakcirculardependency": true,
      "forcealiasattributes": false,
      "useenabledmfas": true
    },
    "codegen": {
      "useappsyncmodelgenplugin": true,
      "usedocsgeneratorplugin": true,
      "usetypesgeneratorplugin": true,
      "cleangeneratedmodelsdirectory": true,
      "retaincasestyle": true,
      "addtimestampfields": true,
      "handlelistnullabilitytransparently": true,
      "emitauthprovider": true,
      "generateindexrules": true,
      "enabledartnullsafety": true,
      "generatemodelsforlazyloadandcustomselectionset": true
    },
    "appsync": {
      "generategraphqlpermissions": true
    },
    "latestregionsupport": {
      "pinpoint": 1,
      "translate": 1,
      "transcribe": 1,
      "rekognition": 1,
      "textract": 1,
      "comprehend": 1
    },
    "project": {
      "overrides": true
    }
  },
  "debug": {
    "shareProjectConfig": false
  }
}

Let us know if this solves your use case.

@royjit royjit removed the follow up Requires follow up from maintainers label Apr 3, 2023
@royjit royjit added closing soon This issue will be closed in 7 days unless further comments are made. pending-community-response Issue is pending response from the issue requestor labels Apr 3, 2023
@royjit royjit self-assigned this Apr 3, 2023
@royjit royjit closed this as completed Apr 20, 2023
@github-actions github-actions bot removed pending-community-response Issue is pending response from the issue requestor closing soon This issue will be closed in 7 days unless further comments are made. labels Apr 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Issues related to the API category bug Something isn't working
Projects
None yet
Development

No branches or pull requests

7 participants