aws-amplify / amplify-swift

A declarative library for application development using cloud services.
Apache License 2.0
455 stars 196 forks source link

API: Error deserializing from error response #591

Closed tappready closed 3 years ago

tappready commented 4 years ago

Describe the bug I am attempting to get the real time sync to work with datastore with zero results even with a subscription the only callbacks I get is local mutations. Upon launch of the app I get the following output in the logs

APIError: subscription item event failed with error Caused by: jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil)))) : [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil)))) 2020-06-28 12:02:25.214300+0100 MyBodyBud[2336:34582] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)

Some extra points: I do attempt to save a UserProfile entry (Model detailed bellow) and this successfully saves locally and the a mutation subscription fires locally but nothing is synced to the cloud. My cloud DynamoDB has the model DietaryRequirement populate with data but this data is not synced locally with datastore.

I am not sure what else I can provide anything else please ask.

Expected behavior I would expect data to sync with backend cloud

Environment(please complete the following information):

Device Information (please complete the following information):

Additional context

type WeightHistory { weight: Float!, dateTime: AWSDateTime! } ... type DietaryRequirement @model @auth(rules: [{ allow: public, operations: [read] }]) @key(name: "orderBy", fields: ["listOrder"]) { id: ID!, description: String!, listOrder: Int! } ...


-
palpatim commented 4 years ago

@tappready Thanks for the details. Can you confirm that you used either Amplify Tools build plugin, or amplify codegen models to regenerate your local models after upgrading Amplify CLI to 4.22.0? I'm not sure whether that would make a difference, but it's good to verify.

palpatim commented 4 years ago

@tappready While we're looking into this, I wanted to call out one other thing. In your configuration code, you specify syncInterval of 30. Unfortunately, this documentation is incorrect. syncInterval actually refers to the maximum interval the system will continue to perform "catch-up" queries. After this interval expires, the system performs a "base" query and retrieves all data.

The actual times at which DataStore performs the sync query aren't directly under your control. Rather, DataStore runs a sync query when it starts new subscriptions: app startup, app returning from foreground, or app restoring network connectivity. At that time, it checks the time at which it performed a "base" query. If less than syncInterval seconds have elapsed since the last "base" query, DataStore runs a "catch-up" query, asking only for data since the last "base" query. Otherwise, if syncInterval has elapsed, DataStore performs a full "base" query and resets the time.

While DataStore is in the foreground and connected, it automatically receives subscriptions from your cloud API via GraphQL subscriptions, so there is no need to specify an aggressive syncInterval to catch those updates.

The default value of syncInterval is 24 hours. So that means if a user of your app launches and retrieves all of their data. The system wouldn't need to perform another full query until 24 hours have elapsed, even if the user quits the app, or backgrounds/foregrounds it, or loses and then restores network.

Hope this clarifies. We'll be fixing the documentation to make that clearer. In the meantime, I'd suggest you can remove your custom configuration.

And of course, we're continuing to investigate the actual bug report. :)

tappready commented 4 years ago

@tappready Thanks for the details. Can you confirm that you used either Amplify Tools build plugin, or amplify codegen models to regenerate your local models after upgrading Amplify CLI to 4.22.0? I'm not sure whether that would make a difference, but it's good to verify.

I have tried with both

tappready commented 4 years ago

@tappready While we're looking into this, I wanted to call out one other thing. In your configuration code, you specify syncInterval of 30. Unfortunately, this documentation is incorrect. syncInterval actually refers to the maximum interval the system will continue to perform "catch-up" queries. After this interval expires, the system performs a "base" query and retrieves all data.

The actual times at which DataStore performs the sync query aren't directly under your control. Rather, DataStore runs a sync query when it starts new subscriptions: app startup, app returning from foreground, or app restoring network connectivity. At that time, it checks the time at which it performed a "base" query. If less than syncInterval seconds have elapsed since the last "base" query, DataStore runs a "catch-up" query, asking only for data since the last "base" query. Otherwise, if syncInterval has elapsed, DataStore performs a full "base" query and resets the time.

While DataStore is in the foreground and connected, it automatically receives subscriptions from your cloud API via GraphQL subscriptions, so there is no need to specify an aggressive syncInterval to catch those updates.

The default value of syncInterval is 24 hours. So that means if a user of your app launches and retrieves all of their data. The system wouldn't need to perform another full query until 24 hours have elapsed, even if the user quits the app, or backgrounds/foregrounds it, or loses and then restores network.

Hope this clarifies. We'll be fixing the documentation to make that clearer. In the meantime, I'd suggest you can remove your custom configuration.

And of course, we're continuing to investigate the actual bug report. :)

That integer was just a suggestion from a member on discord I have removed this since sorry for including it

lawmicha commented 4 years ago

hi @tappready, thanks for reporting this issue. Taking a look at the schema:

type UserProfile
@model(timestamps:{createdAt: "createdOn", updatedAt: "updatedOn"})
@auth(rules: [{ allow: owner, groups: ["Users"] operations: [create, update, read] }])
{
  id: ID!,
  name: String
  weightHistory: [WeightHistory]
}

type WeightHistory {
  weight: Float!,
  dateTime: AWSDateTime!
}

type DietaryRequirement
@model
@auth(rules: [{ allow: public, operations: [read] }])
@key(name: "orderBy", fields: ["listOrder"]) 
{
  id: ID!,
  description: String!,
  listOrder: Int!
}
  1. For UserProfile, you have allow: owner which provides access to the model for authenticated users.
    • Users have to sign into cognito user pool before they are able to successfully create/update/read the data. groups: ["Users"] is used in conjuntion with allow: groups for static group authorizion so it has no effect here. This can be verified by creating a user, not in the Cognito group "Users", sign in via AppSync Queries console, and making a create mutation request to successfully create a UserProfile. You can omit the groups: ["Users:]
    • operations: [create, update, read] also restricts acess to authenticated users to allow create, update, and read the data. By omitting 'delete' from the operations, this means anyone can delete the data given that they are somehow are able to get a hold of the id. I noticed the provisioned backend restricts delete subscription operations to only authenciated users which is why you are seeing the subscription failures. Is your use case actually to allow anyone to delete this data? If not, this will work:
      type UserProfile
      @model(timestamps:{createdAt: "createdOn", updatedAt: "updatedOn"})
      @auth(rules: [{ allow: owner, operations: [create, update, read, delete] }]) // you can also omit `operations` all together, it will default the same shown here
      {
      id: ID!,
      name: String
      weightHistory: [WeightHistory]
      }

If you require the user to be in the cognito user group, use allow: groups and groups:

type UserProfile
@model(timestamps:{createdAt: "createdOn", updatedAt: "updatedOn"})
@auth(rules: [{ allow: groups, groups: ["Users"], operations: [create, update, read, delete] }])
{
  id: ID!,
  name: String
  weightHistory: [WeightHistory]
}
  1. For DietaryRequirement, the allow:public requires the request to be signed with the API key. With operations: [read] you then restrict requests with api key to only allow read operations. Then which users should be able to create the data? Consider combining authorization modes, the example translates to
    type DietaryRequirement
    @model
    @auth(rules: [
    { allow: owner },
    { allow: public, operations: [read] }])
    @key(name: "orderBy", fields: ["listOrder"]) 
    {
    id: ID!,
    description: String!,
    listOrder: Int!
    }

    Only signed in users can create/update/delete/read DietaryRequirement, and requests with api key can only read the data.

This use case creates a single endpoint with multiple auth modes (APIKey, Cognito user pool). One limitation to keep in mind is that DataStore depends on a single API configured. You'll want to make sure your default auth mode is Cognito user pool and additional auth types is API Key (not the other way around)

 Choose the default authorization type for the API `Amazon Cognito User Pool`
Use a Cognito user pool configured as a part of this project.
? Do you want to configure advanced settings for the GraphQL API `Yes, I want to make some additional 
changes.`
? Configure additional auth types? `Yes`
? Choose the additional authorization types you want to configure for the API `API key`

and also make sure DataStore conflict resolution is enabled when using Amplify.DataStore

? Configure conflict detection? `Yes`
? Select the default resolution strategy `Auto Merge`

the resulting amplifyconfiguration.json should be the Cognito User Pool authorization Type for the endpoint

"api": {
        "plugins": {
            "awsAPIPlugin": {
                "[friendlyAPIName]": {
                    "endpointType": "GraphQL",
                    "endpoint": "https://<your endpoint>.us-west-2.amazonaws.com/graphql",
                    "region": "us-west-2",
                    "authorizationType": "AMAZON_COGNITO_USER_POOLS"

I have tested this Amplify Library 1.0.4 and Amplify CLI 4.22.0. Now you can make requests from other places like a web app for the public data by adding API Key to your request to the same AppSync endpoint. When the app is running with DataStore, the subscriptions are expected to fail until the user is signed in. Hope that clears up some of the usage around the auth and model directives.

tappready commented 4 years ago

Hi @lawmicha, thank you so much for your response, time and effort.

I have since removed the groups declaration from my auth. Me omitting 'delete' from the array of operations was an attempt to restrict users from deleting. The 'DietaryRequirement' model is static data that should allow all users and non user to read.

I have taken on board your suggestions with regards to auth and after testing by signing up a user with confirmation code and then checking if the user is signed in I then attempt to save the user profile and still get the same errors in the log and nothing is synced to the cloud (DynamoDB), only saved locally.

On another note, after inspecting the User Profile that was saved locally, I noticed that there is no column linking the model to the congnito user? is this correct?

The log after the user confirms with auth code:

2020-07-10 08:39:46.065168+0100 MyBodyBud[3498:60089] [RemoteSyncEngine] pauseSubscriptions() 2020-07-10 08:39:46.065509+0100 MyBodyBud[3498:60089] [RemoteSyncEngine] pauseMutations() 2020-07-10 08:39:46.065755+0100 MyBodyBud[3498:60089] [RemoteSyncEngine] clearStateOutgoingMutations(storageAdapter:) 2020-07-10 08:39:46.066739+0100 MyBodyBud[3498:60089] [RemoteSyncEngine] initializeSubscriptions(api:storageAdapter:) 2020-07-10 08:39:46.069570+0100 MyBodyBud[3498:60089] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject 2020-07-10 08:39:46.072265+0100 MyBodyBud[3498:60089] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject 2020-07-10 08:39:46.074115+0100 MyBodyBud[3498:60089] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject 2020-07-10 08:39:46.075873+0100 MyBodyBud[3498:60089] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject 2020-07-10 08:39:46.164996+0100 MyBodyBud[3498:60340] Connecting to url ... 2020-07-10 08:39:46.417946+0100 MyBodyBud[3498:60340] WebsocketDidConnect 2020-07-10 08:39:46.418074+0100 MyBodyBud[3498:60340] WebsocketDidConnect, sending init message... 2020-07-10 08:39:46.418167+0100 MyBodyBud[3498:60340] Validating connection 2020-07-10 08:39:46.418303+0100 MyBodyBud[3498:60340] WebsocketDidReceiveMessage - {"payload":{"errors":[{"message":"Both, the \"header\", and the \"payload\" query string parameters are missing","errorCode":400}]},"type":"connection_error"} 2020-07-10 08:39:46.418827+0100 MyBodyBud[3498:60340] The data couldn’t be read because it isn’t in the correct format. 2020-07-10 08:39:46.419231+0100 MyBodyBud[3498:60340] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.) 2020-07-10 08:39:46.419551+0100 MyBodyBud[3498:60340] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.) 2020-07-10 08:39:46.419782+0100 MyBodyBud[3498:60340] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.) 2020-07-10 08:39:46.419859+0100 MyBodyBud[3498:60336] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received completion: failure(DataStoreError: subscription item event failed with error Caused by: APIError: subscription item event failed with error Caused by: jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil)))))

lawmicha commented 4 years ago

Hi @tappready just to make sure nothing is lost in translation, could you provide us with the schema you are using now?

tappready commented 4 years ago

@lawmicha please find bellow my current schema: ` ########################################

User Profile

########################################

type UserProfile
@model(timestamps:{createdAt: "createdOn", updatedAt: "updatedOn"})
@auth(rules: [{ allow: owner }])
{
  id: ID!,
  name: String,
  gender: String,
  activityLevel: String,
  occupationActivity: String,
  weeklyGoal: String,
  bodyType: String,
  dietryRequirments: [String],
  height: Float,
  mesureSystem: String,
  firstMealTime: AWSTime,
  weightHistory: [WeightHistory],
  bmiHistory: [BMIHistory],
  favouriteFood: [FavouriteFood]
}

type WeightHistory {
  weight: Float!,
  dateTime: AWSDateTime!
}

type BMIHistory {
  bmi: Float!,
  dateTime: AWSDateTime!
}

type FavouriteFood {
  id: ID!,
  name: String!,
  source: String!,
  imageURL: AWSURL,
  healthLabel: String,
}

########################################

Application config

########################################

type ActivityLevel
@model
@auth(rules: [
    { allow: owner },
    { allow: public, operations: [read] }])
@key(name: "orderBy", fields: ["listOrder"]) 
{
  id: ID!,
  description: String!,
  listOrder: Int!
}

type OccupationActivity
@model
@auth(rules: [
    { allow: owner },
    { allow: public, operations: [read] }])
@key(name: "orderBy", fields: ["listOrder"]) 
{
  id: ID!,
  description: String!,
  listOrder: Int!
}

type DietaryRequirement
@model
@auth(rules: [
    { allow: owner },
    { allow: public, operations: [read] }])
@key(name: "orderBy", fields: ["listOrder"]) 
{
  id: ID!,
  description: String!,
  listOrder: Int!
}`
lawmicha commented 4 years ago

Hi @tappready, I have tried your schema in this sample.

I noticed that there is no column linking the model to the congnito user? is this correct?

That is correct, the owner field is added as a DynamoDB column and used by the AppSync service. If you'd like this field synchronized in the local store, you can add it as an optional field on the Model itself.

type UserProfile
@model(timestamps:{createdAt: "createdOn", updatedAt: "updatedOn"})
@auth(rules: [{ allow: owner }])
{
  id: ID!,
  // ....
  owner: String
}

When saving the UserProfile, you can leave the owner field empty when creating the model instance

tappready commented 4 years ago

HI @lawmicha thank you again for you reply. I have not managed to get your new suggestions tried and tested as I am facing anew issue with 'Resource is not in the state stackUpdateComplete' when running amplify push.

lawmicha commented 4 years ago

HI @lawmicha thank you again for you reply. I have not managed to get your new suggestions tried and tested as I am facing anew issue with 'Resource is not in the state stackUpdateComplete' when running amplify push.

If it is a new app with data that you're okay with deleting and starting new, you can run amplify delete and recreate from scratch. You can also open an issue over in Amplify CLI repo with additional context about the error you are getting

tappready commented 4 years ago

Hi @lawmicha, in the end I did have to to delete/remove the api and start over (no big deal).

Regarding the actual issue I followed you advice and still no luck. I sign up a new user sign that user In and save the UserProfile model and still nothing is pushed to the cloud (DynamoDB) this is snippet of my sign up code

AuthFunctions.signUp(username: emailValue, password: passwordValue, email: emailValue, completion: {(result) -> Void in
                switch result {
                    case .success(let signUpResult):
                        AuthFunctions.fetchCurrentAuthSession(completion: {(result, error) -> Void in
                            if result?.isSignedIn ?? false {
                                self.saveUserProfile(signUpResult: signUpResult)
                            } else {
                                AuthFunctions.signIn(username: emailValue, password: passwordValue, completion: { signedIn, error -> Void in
                                    if signedIn {
                                        self.saveUserProfile(signUpResult: signUpResult)
                                    }
                                })
                            }
                        })
                    case .failure(let error):
                        self.logger?.log(category: .app, message: "\(error.underlyingError!)")
                        self.removeSpinnerView()
                }

func saveUserProfile(signUpResult: AuthSignUpResult) {
        ModelHandler.save(model: self.appDelegate.currentUser!, completion: { result, error -> Void in
            self.removeSpinnerView()

            if case let .confirmUser(deliveryDetails, _) = signUpResult.nextStep {
                self.deliveryDetails = deliveryDetails
                self.logger?.log(category: .app, message: "Delivery details \(String(describing: deliveryDetails))")

                DispatchQueue.main.async {
                    self.performSegue(withIdentifier: self.confirmSignUpSegueIdentifier, sender: self)
                }
            } else {
                self.logger?.log(category: .app, message: "SignUp Complete")
                DispatchQueue.main.async {
                    self.performSegue(withIdentifier: self.signUpCompleteSegueIdentifier, sender: self)
                }
            }

        })
    }

Ps I have placed the datastore methods in a custom Handler class like so

public static func save<M>(model: M, completion: @escaping (Bool, DataStoreError?) -> Void) where M : Model {
        Amplify.DataStore.save(model) {
            switch $0 {
                case .success:
                    self.logger?.log(category: .database, message: "Saved Model:- \(model.modelName)")
                    completion(true, nil)
                case .failure(let error):
                    self.logger?.log(category: .database, message: "Error saving:- \(error.localizedDescription)")
                    completion(false, error)
            }
        }
    }

Appart from a novice error on my part not using DispatchQueue.main.async correctly I get the following logs

2020-07-24 10:57:39.477077+0100 MyBodyBud[2864:92094] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:39.477208+0100 MyBodyBud[2864:92094] [Client] Updating selectors after delegate addition failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:39.477335+0100 MyBodyBud[2864:92097] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:39.477705+0100 MyBodyBud[2864:92097] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:39.477737+0100 MyBodyBud[2864:92094] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:39.478047+0100 MyBodyBud[2864:92097] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:39.478077+0100 MyBodyBud[2864:92094] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:39.481712+0100 MyBodyBud[2864:92094] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:39.481808+0100 MyBodyBud[2864:92094] [Client] Updating selectors after delegate removal failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.386476+0100 MyBodyBud[2864:92094] [app] [com.apple.root.default-qos] [AuthFunctions.swift:37 fetchCurrentAuthSession(completion:)] > Is user signed in - false
2020-07-24 10:57:40.395722+0100 MyBodyBud[2864:92094] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.395783+0100 MyBodyBud[2864:92093] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.395942+0100 MyBodyBud[2864:92093] [Client] Updating selectors after delegate addition failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.396361+0100 MyBodyBud[2864:92094] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.396394+0100 MyBodyBud[2864:92093] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.396942+0100 MyBodyBud[2864:92094] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.397006+0100 MyBodyBud[2864:92093] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.397948+0100 MyBodyBud[2864:92093] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:40.398079+0100 MyBodyBud[2864:92093] [Client] Updating selectors after delegate removal failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 2864, TID: 92094, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 0
Backtrace:
4   MyBodyBud                           0x000000010f4c9f1d $s9MyBodyBud12ModelHandlerC4save5model10completionyx_ySb_ypSgtct7Amplify0D0RzlFZ + 205
5   MyBodyBud                           0x000000010f548fd3 $s9MyBodyBud20SignUpViewControllerC15saveUserProfile04signE6Resulty7Amplify04AuthdeL0V_tF + 547
6   MyBodyBud                           0x000000010f548d96 $s9MyBodyBud20SignUpViewControllerC02dodE0yyFys6ResultOy7Amplify04AuthdeI0VAG0K5ErrorOGcfU_yAG0K7Session_pSg_AKSgtcfU_ySb_0J7Plugins010AWSCognitokL0OSgtcfU_ + 198
7   MyBodyBud                           0x000000010f5030eb $s9MyBodyBud13AuthFunctionsC6signIn8username8password10completionySS_SSySb_14AmplifyPlugins010AWSCognitoD5ErrorOSgtctFZys6ResultOy0K00d4SigngO0VAN0dN0OGcfU_ + 363
8   AmplifyPlugins                      0x0000000110dfd994 $ss6ResultOy7Amplify010AuthSignInA0VAC0C5ErrorOGIegg_AHIegn_TR + 52
9   Amplify                             0x0000000110a6c005 $s7Amplify0A9OperationC9subscribe14resultListenerAA16UnsubscribeTokenVys6ResultOyq_q0_Gc_tFyAA10HubPayloadVcfU_ + 917
10  Amplify                             0x0000000110a6c24c $s7Amplify0A9OperationC9subscribe14resultListenerAA16UnsubscribeTokenVys6ResultOyq_q0_Gc_tFyAA10HubPayloadVcfU_TA + 92
11  Amplify                             0x0000000110b42877 $s7Amplify16SerialDispatcherV8dispatch2toySayAA16FilteredListenerVG_tFyycfU_ + 631
12  Amplify                             0x0000000110a553d0 $sIeg_IeyB_TR + 48
13  libdispatch.dylib                   0x00000001114ebdf0 _dispatch_call_block_and_release + 12
14  libdispatch.dylib                   0x00000001114ecd64 _dispatch_client_callout + 8
15  libdispatch.dylib                   0x00000001114ef20b _dispatch_queue_override_invoke + 1022
16  libdispatch.dylib                   0x00000001114fe29a _dispatch_root_queue_drain + 351
17  libdispatch.dylib                   0x00000001114feba4 _dispatch_worker_thread2 + 132
18  libsystem_pthread.dylib             0x00007fff5141f9f7 _pthread_wqthread + 220
19  libsystem_pthread.dylib             0x00007fff5141eb77 start_wqthread + 15
2020-07-24 10:57:40.469094+0100 MyBodyBud[2864:92094] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 2864, TID: 92094, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 0
Backtrace:
4   MyBodyBud                           0x000000010f4c9f1d $s9MyBodyBud12ModelHandlerC4save5model10completionyx_ySb_ypSgtct7Amplify0D0RzlFZ + 205
5   MyBodyBud                           0x000000010f548fd3 $s9MyBodyBud20SignUpViewControllerC15saveUserProfile04signE6Resulty7Amplify04AuthdeL0V_tF + 547
6   MyBodyBud                           0x000000010f548d96 $s9MyBodyBud20SignUpViewControllerC02dodE0yyFys6ResultOy7Amplify04AuthdeI0VAG0K5ErrorOGcfU_yAG0K7Session_pSg_AKSgtcfU_ySb_0J7Plugins010AWSCognitokL0OSgtcfU_ + 198
7   MyBodyBud                           0x000000010f5030eb $s9MyBodyBud13AuthFunctionsC6signIn8username8password10completionySS_SSySb_14AmplifyPlugins010AWSCognitoD5ErrorOSgtctFZys6ResultOy0K00d4SigngO0VAN0dN0OGcfU_ + 363
8   AmplifyPlugins                      0x0000000110dfd994 $ss6ResultOy7Amplify010AuthSignInA0VAC0C5ErrorOGIegg_AHIegn_TR + 52
9   Amplify                             0x0000000110a6c005 $s7Amplify0A9OperationC9subscribe14resultListenerAA16UnsubscribeTokenVys6ResultOyq_q0_Gc_tFyAA10HubPayloadVcfU_ + 917
10  Amplify                             0x0000000110a6c24c $s7Amplify0A9OperationC9subscribe14resultListenerAA16UnsubscribeTokenVys6ResultOyq_q0_Gc_tFyAA10HubPayloadVcfU_TA + 92
11  Amplify                             0x0000000110b42877 $s7Amplify16SerialDispatcherV8dispatch2toySayAA16FilteredListenerVG_tFyycfU_ + 631
12  Amplify                             0x0000000110a553d0 $sIeg_IeyB_TR + 48
13  libdispatch.dylib                   0x00000001114ebdf0 _dispatch_call_block_and_release + 12
14  libdispatch.dylib                   0x00000001114ecd64 _dispatch_client_callout + 8
15  libdispatch.dylib                   0x00000001114ef20b _dispatch_queue_override_invoke + 1022
16  libdispatch.dylib                   0x00000001114fe29a _dispatch_root_queue_drain + 351
17  libdispatch.dylib                   0x00000001114feba4 _dispatch_worker_thread2 + 132
18  libsystem_pthread.dylib             0x00007fff5141f9f7 _pthread_wqthread + 220
19  libsystem_pthread.dylib             0x00007fff5141eb77 start_wqthread + 15
2020-07-24 10:57:41.585627+0100 MyBodyBud[2864:92094] [database] [com.apple.root.default-qos] [BaseDataStoreModelHandler.swift:33 save(model:completion:)] > Saved Model:- UserProfile
2020-07-24 10:57:41.586260+0100 MyBodyBud[2864:92094] [app] [com.apple.root.default-qos] [SignUpViewController.swift:222 saveUserProfile(signUpResult:)] > Delivery details Optional(Amplify.AuthCodeDeliveryDetails(destination: Amplify.DeliveryDestination.email(Optional("s***@i***.com")), attributeKey: Optional(Amplify.AuthUserAttributeKey.email)))
2020-07-24 10:57:41.780647+0100 MyBodyBud[2864:92093] [AXRuntimeCommon] Unknown client: MyBodyBud
2020-07-24 10:57:44.625436+0100 MyBodyBud[2864:90154] Can't find keyplane that supports type 4 for keyboard iPhone-PortraitTruffle-NumberPad; using 25683_PortraitTruffle_iPhone-Simple-Pad_Default
2020-07-24 10:57:49.252647+0100 MyBodyBud[2864:92102] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.252723+0100 MyBodyBud[2864:92096] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.252888+0100 MyBodyBud[2864:92096] [Client] Updating selectors after delegate addition failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.253357+0100 MyBodyBud[2864:92102] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.253399+0100 MyBodyBud[2864:92096] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.253775+0100 MyBodyBud[2864:92102] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.253832+0100 MyBodyBud[2864:92096] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.259184+0100 MyBodyBud[2864:92096] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.259334+0100 MyBodyBud[2864:92096] [Client] Updating selectors after delegate removal failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated.}
2020-07-24 10:57:49.349012+0100 MyBodyBud[2864:92096] [app] [com.apple.root.default-qos] [AuthFunctions.swift:93 confirmSignUp(for:with:completion:)] > Confirm signUp succeeded
2020-07-24 10:58:01.744503+0100 MyBodyBud[2864:92102] [RemoteSyncEngine] pauseSubscriptions()
2020-07-24 10:58:01.745047+0100 MyBodyBud[2864:92102] [RemoteSyncEngine] pauseMutations()
2020-07-24 10:58:01.745328+0100 MyBodyBud[2864:92102] [RemoteSyncEngine] clearStateOutgoingMutations(storageAdapter:)
2020-07-24 10:58:01.746235+0100 MyBodyBud[2864:92102] [RemoteSyncEngine] initializeSubscriptions(api:storageAdapter:)
2020-07-24 10:58:01.749473+0100 MyBodyBud[2864:92102] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject
2020-07-24 10:58:01.751910+0100 MyBodyBud[2864:92102] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject
2020-07-24 10:58:01.753915+0100 MyBodyBud[2864:92102] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject
2020-07-24 10:58:01.755665+0100 MyBodyBud[2864:92102] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject
2020-07-24 10:58:01.757913+0100 MyBodyBud[2864:92102] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received subscription: PassthroughSubject
2020-07-24 10:58:01.788760+0100 MyBodyBud[2864:93570] Connecting to url ...
2020-07-24 10:58:01.974833+0100 MyBodyBud[2864:93570] WebsocketDidConnect
2020-07-24 10:58:01.974905+0100 MyBodyBud[2864:93570] WebsocketDidConnect, sending init message...
2020-07-24 10:58:01.974977+0100 MyBodyBud[2864:93570] Validating connection
2020-07-24 10:58:01.975064+0100 MyBodyBud[2864:93570] WebsocketDidReceiveMessage - {"payload":{"errors":[{"message":"Both, the \"header\", and the \"payload\" query string parameters are missing","errorCode":400}]},"type":"connection_error"}
2020-07-24 10:58:01.975424+0100 MyBodyBud[2864:93570] The data couldn’t be read because it isn’t in the correct format.
2020-07-24 10:58:01.975606+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.975884+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.976157+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.976393+0100 MyBodyBud[2864:93573] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received completion: failure(DataStoreError: subscription item event failed with error
Caused by:
APIError: subscription item event failed with error
Caused by:
jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil)))))
2020-07-24 10:58:01.976412+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.976549+0100 MyBodyBud[2864:93576] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received completion: failure(DataStoreError: subscription item event failed with error
Caused by:
APIError: subscription item event failed with error
Caused by:
jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil)))))
2020-07-24 10:58:01.978907+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.979004+0100 MyBodyBud[2864:93576] [AWSModelReconciliationQueue] receiveCompletion: error: DataStoreError: subscription item event failed with error
Caused by:
APIError: subscription item event failed with error
Caused by:
jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil))))
2020-07-24 10:58:01.979066+0100 MyBodyBud[2864:93573] [AWSModelReconciliationQueue] receiveCompletion: error: DataStoreError: subscription item event failed with error
Caused by:
APIError: subscription item event failed with error
Caused by:
jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil))))
2020-07-24 10:58:01.979145+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.979391+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.979396+0100 MyBodyBud[2864:93570] Unsubscribe - A512DA38-CEFB-4B7C-9722-A65A10D92B75
2020-07-24 10:58:01.979542+0100 MyBodyBud[2864:93570] Unsubscribe - 8F6DB92E-81ED-4256-944A-C5D8FCFD5FC1
2020-07-24 10:58:01.979636+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.979674+0100 MyBodyBud[2864:93570] Unsubscribe - 8F53B028-97C5-4E90-B5BA-71A34CE5B7C0
2020-07-24 10:58:01.979862+0100 MyBodyBud[2864:93570] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received completion: finished
2020-07-24 10:58:01.979892+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.980000+0100 MyBodyBud[2864:93570] Unsubscribe - EE43E683-61EC-4DFE-B8E0-653C890EBF50
2020-07-24 10:58:01.980238+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.980263+0100 MyBodyBud[2864:92102] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received completion: failure(DataStoreError: subscription item event failed with error
Caused by:
APIError: subscription item event failed with error
Caused by:
jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil)))))
2020-07-24 10:58:01.980357+0100 MyBodyBud[2864:93570] Unsubscribe - 4EDC0957-5E19-4E4C-9C15-BFF7C0E7C585
2020-07-24 10:58:01.980504+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.980556+0100 MyBodyBud[2864:93570] Unsubscribe - 74E09E02-9454-4E06-B9C2-15D8EF6BCB36
2020-07-24 10:58:01.980562+0100 MyBodyBud[2864:92102] [AWSModelReconciliationQueue] receiveCompletion: error: DataStoreError: subscription item event failed with error
Caused by:
APIError: subscription item event failed with error
Caused by:
jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil))))
2020-07-24 10:58:01.980675+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.980690+0100 MyBodyBud[2864:93570] Unsubscribe - 6E60FA8E-53F7-4111-8975-D60A9E4447E9
2020-07-24 10:58:01.980911+0100 MyBodyBud[2864:93570] Unsubscribe - 0A5297D8-7744-4BA0-A900-AA3A684CBF7F
2020-07-24 10:58:01.980934+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.981026+0100 MyBodyBud[2864:93572] Self is nil, listener is not called.
2020-07-24 10:58:01.981034+0100 MyBodyBud[2864:93570] Unsubscribe - 3F469A96-DB86-43EC-AD35-1AF56DA23604
2020-07-24 10:58:01.981171+0100 MyBodyBud[2864:93570] Unsubscribe - EC9B72F2-B917-47B2-8FD8-D617F7DDA339
2020-07-24 10:58:01.981195+0100 MyBodyBud[2864:93572] The operation couldn’t be completed. (AppSyncRealTimeClient.ConnectionProviderError error 0.)
2020-07-24 10:58:01.981282+0100 MyBodyBud[2864:93570] Unsubscribe - F25DA6DA-41FC-4FDF-BC0C-974258480D53
2020-07-24 10:58:01.981412+0100 MyBodyBud[2864:93570] Unsubscribe - BFF33920-72D9-4FF2-B4B8-CA0B39655526
2020-07-24 10:58:01.981640+0100 MyBodyBud[2864:93570] Unsubscribe - CE7960CF-686D-4534-B097-D05773EEB6AD
2020-07-24 10:58:01.981705+0100 MyBodyBud[2864:93598] [IncomingAsyncSubscriptionEventToAnyModelMapper] Received completion: failure(DataStoreError: subscription item event failed with error
Caused by:
APIError: subscription item event failed with error
Caused by:
jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil)))))
lawmicha commented 4 years ago

Thanks for your patience with this. The errors that I see above is related to the sync engine's subscriptions failing to start. Do they continue to fail even after user signs in and you perform the DataStore.save operation? I think what's missing here might be alignment on the provisioning steps. Can you provide the steps you took to provisioned the API?

Conflict resolution enabled API Did you enable conflict resolution for the API? if you haven't, conflict resolution is required for using DataStore and can be enabled afterwards by running amplify update api and "Enable for DataStore", then amplify push.

Cognito Auth as primary auth mode DId you select cognito auth as primary and then API Key as additional? You can verify the set-up with amplifyconfiguration.json, it should contain for the API using "authorizationType": "AMAZON_COGNITO_USER_POOLS" which represents the primary auth mode. amplify console api will open the AppSync console and then you can check in the Settings that there the additional auth mode is API Key

Amplify configuration Do you have the same or similar code that configures Amplify and related plugins?

Subscriptions failing and succeeding after sign In Subscriptions are expected to fail since the user is required to be authenticated, you can try: signing in, then restarting the app. the session should be persisted and then the subscription errors should go away. This check is the same as making a DataStore operation without re-running the app which will attempt to restart the sync engine.

Bug workaround: Set collection parameters to nil Passing in [] or not passing in any value for collections will default to [] and causeSupplied AttributeValue is empty, must contain exactly one of the supported datatypes. Existing bug here

tappready commented 4 years ago

Thanks for your patience with this. The errors that I see above is related to the sync engine's subscriptions failing to start. Do they continue to fail even after user signs in and you perform the DataStore.save operation? I think what's missing here might be alignment on the provisioning steps. Can you provide the steps you took to provisioned the API?

I cannot remember every option I selected perhaps you can advise on the proper way to fully remove the amplify from my project and the steps that I should take to provision the API. (if the bellow answers are all correct and acceptable)

Conflict resolution enabled API Did you enable conflict resolution for the API? if you haven't, conflict resolution is required for using DataStore and can be enabled afterwards by running amplify update api and "Enable for DataStore", then amplify push.

I have configured Auto Merge

Cognito Auth as primary auth mode DId you select cognito auth as primary and then API Key as additional? You can verify the set-up with amplifyconfiguration.json, it should contain for the API using "authorizationType": "AMAZON_COGNITO_USER_POOLS" which represents the primary auth mode. amplify console api will open the AppSync console and then you can check in the Settings that there the additional auth mode is API Key Cognito is my primary auth option and API key is my secondary

Amplify configuration Do you have the same or similar code that configures Amplify and related plugins?

Yes

           do {
            Amplify.Logging.logLevel = {
                #if DEBUG
                return .debug
                #else
                return .error
                #endif
            }()

            let apiPlugin = AWSAPIPlugin(modelRegistration: AmplifyModels())
            let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels())

            try Amplify.add(plugin: AWSCognitoAuthPlugin())
            try Amplify.add(plugin: apiPlugin)
            try Amplify.add(plugin: dataStorePlugin)
            try Amplify.configure()
            logger?.log(category: .app, message: "Initialized Amplify")
        } catch {
            logger?.log(category: .app, message: "Failed to initialize Amplify with \(error)")
            return false
        }

Subscriptions failing and succeeding after sign In Subscriptions are expected to fail since the user is required to be authenticated, you can try: signing in, then restarting the app. the session should be persisted and then the subscription errors should go away. This check is the same as making a DataStore operation without re-running the app which will attempt to restart the sync engine.

Ok so are you suggesting calling save after the users verification has been confirmed? In my previous comment I show that I call signIn before calling save and save is called within the completion block. Should the auth engine not have signed in the user if verification was needed?

Bug workaround: Set collection parameters to nil Passing in [] or not passing in any value for collections will default to [] and causeSupplied AttributeValue is empty, must contain exactly one of the supported datatypes. Existing bug here

I have catered for this

        if (newUserProfile?.weightHistory?.isEmpty) != nil {
            newUserProfile?.weightHistory = nil
        }

        if (newUserProfile?.bmiHistory?.isEmpty) != nil {
            newUserProfile?.bmiHistory = nil
        }

        if (newUserProfile?.favouriteFood?.isEmpty) != nil {
            newUserProfile?.favouriteFood = nil
        }
tappready commented 4 years ago

@lawmicha

Latest update I fully removed and delete the api and now get the following error when appearing to list a model that is currently only available in the cloud

2020-08-10 22:43:13.315945+0100 MyBodyBud[9594:205267] [AWSModelReconciliationQueue] receiveCompletion: error: DataStoreError: subscription item event failed with error
Caused by:
APIError: subscription item event failed with error
Caused by:
jsonParse(nil, Optional(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "type", intValue: nil)], debugDescription: "Cannot initialize RealtimeConnectionProviderResponseType from invalid String value connection_error", underlyingError: nil))))

I was attempting to list the following model while not signed in

type ActivityLevel
@model
@auth(rules: [
    { allow: owner },
    { allow: public, operations: [read] }])
@key(name: "orderBy", fields: ["listOrder"]) 
{
  id: ID!,
  description: String!,
  listOrder: Int!
} 

Bellow is the setup (I have masked sensitive name with ****)

********@********-MBP ******** % amplify init
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project ********
? Enter a name for the environment dev
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building ios
Using default provider  awscloudformation

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html

? Do you want to use an AWS profile? Yes
? Please choose the profile you want to use ********
Adding backend environment dev to AWS Amplify Console app: ********
⠴ Initializing project in the cloud...

CREATE_IN_PROGRESS AuthRole                     AWS::IAM::Role             Mon Aug 10 2020 15:01:35 GMT+0100 (British Summer Time) Resource creation Initiated
CREATE_IN_PROGRESS UnauthRole                   AWS::IAM::Role             Mon Aug 10 2020 15:01:35 GMT+0100 (British Summer Time) Resource creation Initiated
CREATE_IN_PROGRESS DeploymentBucket             AWS::S3::Bucket            Mon Aug 10 2020 15:01:35 GMT+0100 (British Summer Time)                            
CREATE_IN_PROGRESS AuthRole                     AWS::IAM::Role             Mon Aug 10 2020 15:01:35 GMT+0100 (British Summer Time)                            
CREATE_IN_PROGRESS UnauthRole                   AWS::IAM::Role             Mon Aug 10 2020 15:01:34 GMT+0100 (British Summer Time)                            
CREATE_IN_PROGRESS amplify-********-dev-150129 AWS::CloudFormation::Stack Mon Aug 10 2020 15:01:30 GMT+0100 (British Summer Time) User Initiated             
⠦ Initializing project in the cloud...

CREATE_IN_PROGRESS DeploymentBucket AWS::S3::Bucket Mon Aug 10 2020 15:01:36 GMT+0100 (British Summer Time) Resource creation Initiated
⠧ Initializing project in the cloud...

CREATE_COMPLETE UnauthRole AWS::IAM::Role Mon Aug 10 2020 15:01:50 GMT+0100 (British Summer Time) 
⠦ Initializing project in the cloud...

CREATE_COMPLETE AuthRole AWS::IAM::Role Mon Aug 10 2020 15:01:51 GMT+0100 (British Summer Time) 
⠴ Initializing project in the cloud...

CREATE_COMPLETE amplify-********-dev-150129 AWS::CloudFormation::Stack Mon Aug 10 2020 15:01:59 GMT+0100 (British Summer Time) 
CREATE_COMPLETE DeploymentBucket             AWS::S3::Bucket            Mon Aug 10 2020 15:01:56 GMT+0100 (British Summer Time) 
✔ Successfully created initial AWS cloud resources for deployments.
✔ Initialized provider successfully.
Initialized your environment successfully.

Your project has been successfully initialized and connected to the cloud!

Some next steps:
"amplify status" will show you what you've added already and if it's locally configured or deployed
"amplify add <category>" will allow you to add features like user login or a backend API
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify console" to open the Amplify Console and view your project status
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

Pro tip:
Try "amplify add api" to create a backend API and then "amplify publish" to deploy everything

********@********-MBP ******** % amplify add api
? Please select from one of the below mentioned services: GraphQL
? Provide API name: ********
? Choose the default authorization type for the API Amazon Cognito User Pool
Using service: Cognito, provided by: awscloudformation

 The current configured provider is Amazon Cognito. 

 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Email or Phone Number
 Do you want to configure advanced settings? Yes, I want to make some additional changes.
 Warning: you will not be able to edit these selections. 
 What attributes are required for signing up? Email, Phone Number (This attribute is not supported by Facebook, Login With Amazon.)
 Do you want to enable any of the following capabilities? 
Successfully added auth resource
? Do you want to configure advanced settings for the GraphQL API Yes, I want to make some additional changes.
? Configure additional auth types? Yes
? Choose the additional authorization types you want to configure for the API API key
API key configuration
? Enter a description for the API key: ********APIKey
? After how many days from now the API key should expire (1-365): 7
? Configure conflict detection? Yes
? Select the default resolution strategy Auto Merge
? Do you have an annotated GraphQL schema? No
? Choose a schema template: Objects with fine-grained access control (e.g., a project management app with owner-based authorization)

GraphQL schema compiled successfully.

Edit your schema at ../schema.graphql or place .graphql files in a directory at ../schema
? Do you want to edit the schema now? No
Successfully added resource ******** locally

Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

********@********-MBP ******** % amplify push
lawmicha commented 3 years ago

Hi @tappready, sorry for the delay. For what it's worth, there has been quite some work done on DataStore for using the auth directive and it should be more stable, however i noticed with your schema it is using multi-auth set up for the model. The missing feature is multi-auth support so your app will continue to function against the primary auth mode which is user pools (that is what you have correctly configured) but when the user is not signed in, it will not fall back to the API key as the auth mode (this is the missing multi-auth feature).

I followed your provisioning steps with a few notes here

import SwiftUI
import Amplify
import Combine

struct ContentView: View {
    var subscriber: AnyCancellable?
    init() {
        subscriber = Amplify.DataStore.publisher(for: ActivityLevel.self).sink { (completion) in
            print(completion)
        } receiveValue: { (mutationEvent) in
            print("Got event back: \(mutationEvent)")
        }
    }
    func signIn(username: String, password: String) {
        Amplify.Auth.signIn(username: username, password: password) { result in
            switch result {
            case .success:
                print("Sign in succeeded")
            case .failure(let error):
                print("Sign in failed \(error)")
            }
        }
    }
    var body: some View {
        VStack {
            Button("Sign in") {
                signIn(username: "mlaw135@gmail.com", password: "password")
            }
            Button("DataStore call") {
                let activityLevel = ActivityLevel(description: "description", listOrder: 1)
                Amplify.DataStore.save(activityLevel) { (result) in
                    switch result {
                    case .success(let result):
                        print("Save successful \(result)")
                    case .failure(let error):
                        print("DataStore save failed with \(error)")
                    }
                }
            }

        }
    }
}

I ran this on two simulators, and clicked on Sign In on both. Using the one without the debugger attached, I clicked on the API call to save data to the local store and it synced to the cloud, triggering the subscriptions on the app with the debugger attached.

I also noticed that if the user is not signed in, datastore sync engine will fail, then when the user signs in, it may take some time for the retry to kick in to restart the subscriptions. You should be able to verify that the subscriptions are working by re-running the app on the simulator which will kick off the sync engine again. We're also working on a feature that will let you control when to start and stop the sync engine, which you can add in the successful callback of the sign in.

lawmicha commented 3 years ago

i'm going to mark this as feature request based on this schema:

type ActivityLevel
@model
@auth(rules: [
    { allow: owner },
    { allow: public, operations: [read] }])
@key(name: "orderBy", fields: ["listOrder"]) 
{
  id: ID!,
  description: String!,
  listOrder: Int!
} 
  1. Support for auth on the model with multiple rules. allow: owner and allow: public. When the user is not signed in, the data should be read-able using the API key as the secondary auth mode.
  2. After the user signs in, I should have a way to immediately restart datastore. ie. DataStore.stop/DataStore.start
zeman-88 commented 3 years ago

@lawmicha is the conclusion that as of today we can't use Amplify.DataStore.publisher until a user is signed in? I.e. we can't use that with IAM or the API Key sign in modes?

tappready commented 3 years ago

@lawmicha Thank you for your response I can see that there is documentation for DataStore.stop/start at but after an update of all my nom packages and pods I still cannot seem to see any implementation. Can you verify please.

@zeman-88 As I understood and experienced I belieave if your primary auth is Cognito User Pools (needed if you wish to configure authorization models) you are unable to use your secondary auth (API Key) to load models and that and auth rules of public is also not supported hence my need to use API Key

diegocstn commented 3 years ago

@tappready we release DataStore.start/stop as part of Amplify 1.5.0. Were you able to leverage on the them to solve one of your issue?

tappready commented 3 years ago

@diegocstn Thank you for your response. Yes I was able to utilise DataStore.start/stop and DataStoreSyncExpression

Can I ask if you have an update regarding support for auth on the model with multiple rules. allow: owner and allow: public. When the user is not signed in, the data should be read-able using the API key as the secondary auth mode.

diegocstn commented 3 years ago

@tappready we released support for multi-auth as part of v1.12.0. You can read more about multi-auth and DataStore here. I'll optimistically close this, but feel free to re-open if you need more help :)