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

[DataStore.Flutter] Android sourced mutation not working on iOS with schema #3547

Open
lawmicha opened this issue Mar 5, 2024 · 2 comments
Labels
bug Something isn't working datastore Issues related to the DataStore category

Comments

@lawmicha
Copy link
Member

lawmicha commented Mar 5, 2024

I was able to reproduce this with the following app, schema, and steps.

App

import 'package:amplify_api/amplify_api.dart';
import 'package:amplify_datastore/amplify_datastore.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:flutter/material.dart';
import 'package:issue_3654/amplifyconfiguration.dart';
import 'package:issue_3654/models/ModelProvider.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    _configureAmplify();
  }

  Future<void> _configureAmplify() async {
    final api = AmplifyAPI();
    final ds = AmplifyDataStore(modelProvider: ModelProvider.instance);
    await Amplify.addPlugins([api, ds]);

    try {
      await Amplify.configure(amplifyconfig);
    } on AmplifyAlreadyConfiguredException {
      safePrint(
          'Tried to reconfigure Amplify; this can occur when your app restarts on Android.');
    }

    observeQueryMessage();
  }

  void observeQueryMessage() {
    Amplify.DataStore.observeQuery(
      Message.classType,
    ).listen((QuerySnapshot<Message> snapshot) {
      safePrint(
        'Query snapshot received: ${snapshot.items.length} messages, isSynced: ${snapshot.isSynced}',
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Future<void> saveMessage() async {
    safePrint("start saving message");
    User sender = User(
      email: 'example@gmail.com',
      birthdate: TemporalDate(DateTime.now()),
      gender: Gender.male,
      nickname: 'nickname',
    );

    await Amplify.DataStore.save(sender);

    CustomMarker circle = CustomMarker(
      latitude: 1.0,
      longitude: 1.0,
      hostUser: sender,
      purpose: Purpose.exchange,
      title: 'title',
      gatheringTime: TemporalDateTime(DateTime.now()),
      maxParticipants: 0,
      minAge: 0,
      maxAge: 0,
      numParticipants: 0,
    );

    await Amplify.DataStore.save(circle);

    Message message = Message(
      content: 'content',
      sender: sender,
      circle: circle,
      createdOn: TemporalDateTime(DateTime.now().toUtc()),
    );
    await Amplify.DataStore.save(message);
    safePrint('message saved');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Hello world'),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: saveMessage,
        tooltip: 'save',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Schema

enum Gender {
  male
  female
  other
}

enum UserStatus {
  student
  worker
  doctor
  other
}

type User
  @model
  @auth(
    rules: [{ allow: public, operations: [create, read, update, delete] }]
  ) {
  id: ID!
  email: String!
  phone: String
  birthdate: AWSDate!
  gender: Gender!
  userStatus: UserStatus
  nickname: String!
  comment: String
  imageURL: String
  messages: [Message] @hasMany(indexName: "MessageByUser", fields: ["id"])
  hostedCircles: [CustomMarker]
    @hasMany(indexName: "CustomMarkerByHostUser", fields: ["id"])
  participatedCircles: [CustomMarker]
    @manyToMany(relationName: "UserCustomMarkerParticipants")
}

enum Purpose {
  play
  food
  taxi
  exchange
  helpme
}

type CustomMarker @model @auth(rules: [{ allow: public }]) {
  id: ID!
  latitude: Float!
  longitude: Float!
  hostUserID: ID! @index(name: "CustomMarkerByHostUser")
  hostUser: User! @belongsTo(fields: ["hostUserID"])
  purpose: Purpose!
  title: String!
  comment: String
  gatheringTime: AWSDateTime!
  maxParticipants: Int!
  minAge: Int!
  maxAge: Int!
  allowGender: Gender
  numParticipants: Int!
  messages: [Message]
    @hasMany(indexName: "MessageByCustomMarker", fields: ["id"])
  participants: [User] @manyToMany(relationName: "UserCustomMarkerParticipants")
  circleImageURL: String
}

type Message @model @auth(rules: [{ allow: public }]) {
  id: ID!
  content: String!
  createdOn: AWSDateTime!
  senderID: ID! @index(name: "MessageByUser")
  sender: User! @belongsTo(fields: ["senderID"])
  circleID: ID! @index(name: "MessageByCustomMarker")
  circle: CustomMarker! @belongsTo(fields: ["circleID"])
}

Steps:

  1. Save item on iOS, observe that Android receives the data
  2. Save item on Android, observe that iOS does NOT receive data.

Note: If the app is closed/re-opened on iOS, the data does sync in the next delta sync.

Originally posted by @Jordan-Nelson in aws-amplify/amplify-flutter#3654 (comment)

Copy link

github-actions bot commented Mar 5, 2024

This issue was opened by a maintainer of this repository; updates will be posted here. If you are also experiencing this issue, please comment here with any relevant information so that we're aware and can prioritize accordingly.

@lawmicha lawmicha added bug Something isn't working datastore Issues related to the DataStore category labels Mar 5, 2024
@lawmicha
Copy link
Member Author

lawmicha commented Mar 5, 2024

To reproduce this, use the schema and create a backend with it and replay the requests using AppSync console if we have the selection set readily available (see aws-amplify/amplify-flutter#3654 (comment)). If not, create Flutter app using the sample code from description, and create a Swift app sharing the same backend, and perform saves sourced from the Android Flutter app, to observe the behavior on DataStore Swift v1 app.

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

1 participant