aws-amplify / amplify-flutter

A declarative library with an easy-to-use interface for building Flutter applications on AWS.
https://docs.amplify.aws
Apache License 2.0
1.32k stars 247 forks source link

ModelQueries.list fails randomly without any logs #5357

Open harini18 opened 2 months ago

harini18 commented 2 months ago

Description

ModelQueries.list response does not return sometimes. I am able to get the right values like 10% of the time, rest of the time there is no reply and no logs to debug this issue.

Categories

Steps to Reproduce

My Schema:

 Goal: a
    .model({
      direction: a.enum(["INCREASE", "DECREASE"]),
      from: a.float(),
      to: a.float(),
      vitalId: a.id().required(),
      vital: a.belongsTo("Vital", "vitalId"),
      eventId: a.id().required(),
      event: a.belongsTo("Event", "eventId"),
    })
    .authorization((allow) => [allow.owner()]),
  // Vitals Related
  StandardVital: a
    .model({
      name: a.string(),
      vitals: a.hasMany("Vital", "standardVitalId"),
    })
    .authorization((allow) => [
      allow.authenticated().to(["read"]),
      allow.group("Admin"),
    ]),
  CustomVital: a
    .model({
      name: a.string(),
      vitals: a.hasMany("Vital", "customVitalId"),
    })
    .authorization((allow) => [allow.owner()]),
  Vital: a
    .model({
      standardVitalId: a.id(),
      standardVital: a.belongsTo("StandardVital", "standardVitalId"),
      customVitalId: a.id(),
      customVital: a.belongsTo("CustomVital", "customVitalId"),
      goalId: a.id(),
      goal: a.hasOne("Goal", "vitalId"),
      vitalMeasurementLogs: a.hasMany("VitalMeasurementLog", "vitalId"),
    })
    .authorization((allow) => [allow.owner()]),

My Query:

try {
      final request = ModelQueries.list(
        Goal.classType,
        where: Goal.EVENT.eq(event.id),
      );
      final response = await Amplify.API.query(request: request).response;

      if (response.hasErrors) {
        safePrint('errors: ${response.errors}');
        return [];
      }

      final goals = response.data?.items ?? <Goal?>[];

      return goals;
    } on Exception catch (e) {
      safePrint(e);
      rethrow;
    }

For some reason - I don't get response. When I try to debug, the code does flow through after final response = await Amplify.API.query(request: request).response;. There are no logs in VSCode and there are no exceptions that are thrown.

No Idea what is happening.

I am creating this object using:

// Create Vital
    final newVital = Vital(id: uuid(), standardVital: standardVital);

    final vitalRequest = ModelMutations.create(newVital);
    final vitalResponse =
        await Amplify.API.mutate(request: vitalRequest).response;

    if (vitalResponse.data == null) {
      throw Exception("Goal Creation Failed");
    }

    final newlyCreatedVital = (await Amplify.API
            .query(
                request: ModelQueries.get(
                    Vital.classType, vitalResponse.data!.modelIdentifier))
            .response)
        .data;

    // Create Goal
    final newGoal = Goal(
        id: uuid(),
        event: event,
        direction: goalDirection,
        vital: newlyCreatedVital,
        from: from,
        to: to);
    final request = ModelMutations.create(newGoal);
    final response = await Amplify.API.mutate(request: request).response;

Screenshots

No response

Platforms

Flutter Version

3.24.0

Amplify Flutter Version

2.0.0

Deployment Method

Amplify CLI

Schema

No response

NikaHsn commented 2 months ago

Sorry that you are facing this issue and thanks for reporting it. does it only happen on iOS?

harini18 commented 2 months ago

Yes in iOS emulator.

NikaHsn commented 2 months ago

thanks for confirming. we will look into this issue and get back to you with any updates.

harini18 commented 2 months ago

Any updates - we are blocked completely.

Jordan-Nelson commented 2 months ago

@harini18 - This is currently in our backlog of issues to attempt to reproduce.

Was this previously working on iOS?

harini18 commented 2 months ago

No it never worked.

Jordan-Nelson commented 2 months ago

@harini18 Can you use Flutter dev tools to monitor the network traffic (see: https://docs.flutter.dev/tools/devtools/network) and share a screenshot of the request/response? Do you see the request complete in the dev tools?

harini18 commented 2 months ago

Create Vitals

Request:

{"variables":{"input":{"id":"c6f037ff-86aa-4e01-8b84-76388a105dce","standardVitalId":"328d85f0-e1e9-4d99-a71c-38351f42e54e"}},"query":"mutation createVital($input: CreateVitalInput!, $condition: ModelVitalConditionInput) { createVital(input: $input, condition: $condition) { id createdAt updatedAt standardVital { id name createdAt updatedAt } standardVitalId customVital { id name createdAt updatedAt owner } customVitalId goal { id direction from to createdAt updatedAt owner } goalId owner } }"} Response: {"data":{"createVital":{"id":"c6f037ff-86aa-4e01-8b84-76388a105dce","createdAt":"2024-08-30T13:29:14.740Z","updatedAt":"2024-08-30T13:29:14.740Z","standardVital":null,"standardVitalId":"328d85f0-e1e9-4d99-a71c-38351f42e54e","customVital":null,"customVitalId":null,"goal":null,"goalId":null,"owner":"4801b350-9091-70f1-1e36-3f4990f754b5"}},"errors":[{"path":["createVital","standardVital","id"],"locations":null,"message":"Cannot return null for non-nullable type: 'ID' within parent 'StandardVital' (/createVital/standardVital/id)"},{"path":["createVital","standardVital","createdAt"],"locations":null,"message":"Cannot return null for non-nullable type: 'AWSDateTime' within parent 'StandardVital' (/createVital/standardVital/createdAt)"},{"path":["createVital","standardVital","updatedAt"],"locations":null,"message":"Cannot return null for non-nullable type: 'AWSDateTime' within parent 'StandardVital' (/createVital/standardVital/updatedAt)"},{"path":["createVital","customVital","id"],"locations":null,"message":"Cannot return null for non-nullable type: 'ID' within parent 'CustomVital' (/createVital/customVital/id)"},{"path":["createVital","customVital","createdAt"],"locations":null,"message":"Cannot return null for non-nullable type: 'AWSDateTime' within parent 'CustomVital' (/createVital/customVital/createdAt)"},{"path":["createVital","customVital","updatedAt"],"locations":null,"message":"Cannot return null for non-nullable type: 'AWSDateTime' within parent 'CustomVital' (/createVital/customVital/updatedAt)"},{"path":["createVital","goal","id"],"locations":null,"message":"Cannot return null for non-nullable type: 'ID' within parent 'Goal' (/createVital/goal/id)"},{"path":["createVital","goal","createdAt"],"locations":null,"message":"Cannot return null for non-nullable type: 'AWSDateTime' within parent 'Goal' (/createVital/goal/createdAt)"},{"path":["createVital","goal","updatedAt"],"locations":null,"message":"Cannot return null for non-nullable type: 'AWSDateTime' within parent 'Goal' (/createVital/goal/updatedAt)"}]}

Get Vital

Request

{"variables":{"id":"c6f037ff-86aa-4e01-8b84-76388a105dce"},"query":"query getVital($id: ID!) { getVital(id: $id) { id createdAt updatedAt standardVital { id name createdAt updatedAt } standardVitalId customVital { id name createdAt updatedAt owner } customVitalId goal { id direction from to createdAt updatedAt owner } goalId owner } }"}

Response {"data":{"getVital":{"id":"c6f037ff-86aa-4e01-8b84-76388a105dce","createdAt":"2024-08-30T13:29:14.740Z","updatedAt":"2024-08-30T13:29:14.740Z","standardVital":{"id":"328d85f0-e1e9-4d99-a71c-38351f42e54e","name":"Body Fat Percentage","createdAt":"2024-08-21T01:16:27.358Z","updatedAt":"2024-08-21T01:16:27.358Z"},"standardVitalId":"328d85f0-e1e9-4d99-a71c-38351f42e54e","customVital":null,"customVitalId":null,"goal":null,"goalId":null,"owner":"4801b350-9091-70f1-1e36-3f4990f754b5"}}}

Create Goal

Request {"variables":{"input":{"id":"84c1a806-82bf-4f39-8c04-73e761402ed9","direction":"DECREASE","from":26.0,"to":20.0,"eventId":"6bab29a4-a120-4b7f-8c0a-e904b4ac30c4"}},"query":"mutation createGoal($input: CreateGoalInput!, $condition: ModelGoalConditionInput) { createGoal(input: $input, condition: $condition) { id direction from to createdAt updatedAt event { id name date createdAt updatedAt owner } eventId owner } }"}

Response {"data":null,"errors":[{"path":null,"locations":[{"line":1,"column":21,"sourceName":null}],"message":"Variable 'input' has coerced Null value for NonNull type 'ID!'"}]}

Jordan-Nelson commented 2 months ago

Thanks for providing that. We will attempt to reproduce.

harini18 commented 2 months ago

Any updates?

NikaHsn commented 2 months ago

@harini18 we will attempt to reproduce this and will provide updates here as we have them. sorry for the delay and thanks for your patience.

harini18 commented 1 month ago

Given it is has been 2 weeks, and we are completely blocked, it will be great if you could at least look at my code and see if I am doing anything wrong.

Thanks for your help

NikaHsn commented 1 month ago

@harini18 the provided model is missing event, would you please share the event model. as I didn't have the event model, I tried to reproduce this issue listing goals by vitalId and was not able to reproduce this issue. can you confirm if the created goals in the dynamoDB table have event id?

harini18 commented 1 month ago

// Event Related

  Event: a
    .model({
      name: a.string(),
      date: a.date(),
      plans: a.hasMany("Plan", "eventId"),
      goals: a.hasMany("Goal", "eventId"),
      owner: a
        .string()
        .authorization((allow) => [allow.owner().to(["read", "delete"])]),
    })
    .authorization((allow) => [allow.owner()]),

I am not even able to create goals. I am getting "message":"Variable 'input' has coerced Null value for NonNull type 'ID!'"

NikaHsn commented 1 month ago

would you please share the full graphql response for creating a goal. do you pass all the required field when creating a goal?

harini18 commented 1 month ago

Create Goal

Request {"variables":{"input":{"id":"84c1a806-82bf-4f39-8c04-73e761402ed9","direction":"DECREASE","from":26.0,"to":20.0,"eventId":"6bab29a4-a120-4b7f-8c0a-e904b4ac30c4"}},"query":"mutation createGoal($input: CreateGoalInput!, $condition: ModelGoalConditionInput) { createGoal(input: $input, condition: $condition) { id direction from to createdAt updatedAt event { id name date createdAt updatedAt owner } eventId owner } }"}

Response {"data":null,"errors":[{"path":null,"locations":[{"line":1,"column":21,"sourceName":null}],"message":"Variable 'input' has coerced Null value for NonNull type 'ID!'"}]}

harini18 commented 1 month ago

// Create Goal final newGoal = Goal( id: uuid(), event: event, direction: goalDirection, vital: newlyCreatedVital, from: from, to: to); final request = ModelMutations.create(newGoal); final response = await Amplify.API.mutate(request: request).response;

Equartey commented 1 month ago

Hi @harini18,

It looks like your request to create a Goal does not contain a Vital in the input variable. I suspect that's the reason you're seeing "Variable 'input' has coerced Null value for NonNull type 'ID!'".

final newlyCreatedVital = (await Amplify.API
            .query(
                request: ModelQueries.get(
                    Vital.classType, vitalResponse.data!.modelIdentifier))
            .response)
        .data;

In the above code snippet can you verify the newlyCreatedVital you query has value before creating a Goal with it?