Skip to content

[cloud_firestore] Created firestore platform interface #1686

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

Merged
merged 21 commits into from
Feb 5, 2020

Conversation

amrfarid140
Copy link
Contributor

Description

This PR is the first of a set of 3 PRs to enable Flutter Web support for Cloud Firestore.

All the discussion around approach and logic are being actively discussed here.

Related Issues

flutter/flutter#45293

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • If the pull request affects only one plugin, the PR title starts with the name of the plugin in brackets
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (please indicate a breaking change in CHANGELOG.md and increment major revision).
  • No, this is not a breaking change.

@amrfarid140
Copy link
Contributor Author

@ditman That's the first one to get cloud_firestore_platform_interface published.

@ditman
Copy link
Contributor

ditman commented Dec 21, 2019

@collinjackson, this is the real deal. Most of the work has happened here, but this is what we want to land. PTAL when you have a chance!

@ditman ditman requested a review from amirh December 21, 2019 01:21
@ditman
Copy link
Contributor

ditman commented Dec 21, 2019

(I'll also be taking another look)

Copy link
Contributor

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks great, there's a bunch of double quotes across the code, but those can be added later, alongside tightening the lint rules. Only one general comment, the structure of the package under src is a little bit too flat, I think it'd be cool to have a few directories to separate interfaces from implementations (and maybe types). Since everything is part'd in, it should be easy to add afterwards.

Let's wait for Collin's review, but other than the minor nitpicks in this review, I can't find anything that is immediately problematic.

Again, thanks for all this code!

Copy link
Contributor

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

88           ,ad8888ba,  888888888888  88b           d88  
88          d8"'    `"8b      88       888b         d888  
88         d8'                88       88`8b       d8'88  
88         88                 88       88 `8b     d8' 88  
88         88      88888      88       88  `8b   d8'  88  
88         Y8,        88      88       88   `8b d8'   88  
88          Y8a.    .a88      88       88    `888'    88  
88888888888  `"Y88888P"       88       88     `8'     88
Looks Good To Me

amrfarid140 and others added 2 commits December 23, 2019 07:50
Analyzer is complaining about this extra carriage return.
Copy link
Contributor

@collinjackson collinjackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for contributing this change! A web implementation of Firestore in FlutterFire is a top requested feature and I'm sure this will help a lot of people.

Here's my initial round of comments; I'm expect I may have a few more once these are addressed.

Please make sure to follow the Effective Dart guide for Dart throughout. In particular please follow these guidelines:

  • have a blank line after the first sentence
  • put a period at the end of the first line
  • avoid redundancy with the surrounding context (e.g. no need to repeat the class name in the constructor's documentation)

Thanks!!

throw UnimplementedError("withApp() not implemented");
}

/// Firebase app name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to expose a FirebaseApp here instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FirebaseApp is already exposed to avoid breaking changes. This is just a convenience used in few places in here

static int _transactionHandlerId = 0;

@override
FirestorePlatform withApp(FirebaseApp app) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if we can call this instanceFor({ FirebaseApp app }) to match #1377

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point we already have a factory method of the FirestorePlatform called instanceFor. We won't be able to rename this as well to instanceFor. Also this is only made public so FirestoreWeb (in the web plugin) is able to override it and provide a web-specific implementation.

@grundid
Copy link

grundid commented Jan 7, 2020

A small suggestion here: can we have a flutter independent API for firestore? As this package mainly consists of interfaces it would be great to move them into a new package that is pure dart and then depend on it.

There are already many attempts to create platform independent APIs for firestore. We ourself also created one (https://github.com/dartclub/firestore_dart).
Based on our API we are working on a firestore serializer (similar to the json_serializer) that is able to generate code to read and write data to and from firestore. To make this serializer universal we depend on an API for firestore.

@ditman
Copy link
Contributor

ditman commented Jan 7, 2020

can we have a flutter independent API for firestore? As this package mainly consists of interfaces it would be great to move them into a new package that is pure dart and then depend on it.

@grundid that's a great suggestion, but for now we're focusing on merging this, so people can use Firestore on their Flutter apps. Further abstraction sounds possible (but it also sounds as a v2 project for this change)

@ditman
Copy link
Contributor

ditman commented Jan 17, 2020

@amrfarid140 I was just finishing testing this on my new test app. Great stuff!

Copy link
Contributor

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should ship this. What do you think @collinjackson?

@amrfarid140
Copy link
Contributor Author

@collinjackson any updates or feedback on this PR? Really want to merge to move on with other parts of the web implementation as well.

@ditman
Copy link
Contributor

ditman commented Jan 29, 2020

Hey @amrfarid140! Apologies for the radio silence!

We're about to send you a PR with a few little changes to the platform interface (and things that depend on them). Most of them are some moving around of files (so files regarding platform interfaces live together, same with files regarding the method channel), and some renaming so everything is consistent.

The only (big-ish) issue that was found was that the Web versions of the platform interfaces are using implements, and that basically means that we cannot change the interface, or it'll break the web implementation.

I'm currently adding the extends PlatformInterface to all the PlatformInterface objects, so we can prevent the implements from happening, and it is intentional.

Bear in mind that this PR is going to be used by many as an "example" on how to build their own plugins, so we need to make sure there's nothing very dangerous here (at least, that we know of now).

So by EOD today I'll cut a PR to your repo with the changes to the platform interface and method channel code, and maybe some changes to the Web implementation (just to keep the branch functional!)

I'll get back to you ASAP. If you want to privately message me, feel free to do so at: (first half of my github username) at google dot com ;)

@amrfarid140
Copy link
Contributor Author

amrfarid140 commented Jan 29, 2020 via email

@ditman
Copy link
Contributor

ditman commented Feb 3, 2020

Hey @amrfarid140, it seems I can't create a pull request on your fork. Do you mind giving me permissions to do that? Thanks!

@ditman
Copy link
Contributor

ditman commented Feb 3, 2020

Hey @amrfarid140, I still can't create PRs on your fork (maybe some weird github issue?) but I've pushed my changes here:

https://github.com/amrfarid140/flutterfire/commits/amr-master-pr

This is prepared on top of your master branch. We've touched all packages, and not just the platform interface (so future PRs for the other 2 packages should be smoother as well).

I think @collinjackson still wants to propose some changes, but I can help with those pretty quickly, once the PR(s) are updated with the above.

The bulk of the changes was to remove the API surface exposed to the world through the different packages of the plugin (MethodChannel implementation, Web implementation), and ensure the Platform classes all extended PlatformInterface so they are extended vs implemented.

I'd say by "size":

  1. changes are moving files around,
  2. the extends thing and
  3. making things that shouldn't be imported by the end user "private".
  4. Some formatting and dart analysis and all that.

I ran tests and they seem to pass.

@amrfarid140
Copy link
Contributor Author

amrfarid140 commented Feb 3, 2020

Yeah that's weird @ditman , I've added you as a collaborator and made sure that "allow edits from maintainers" is checked. Anyways, Thanks so much for those changes. I will get all the packages sorted and all those changes to the master branch to update the PRs ASAP.

I will also do some testing as well to ensure that we are all good.

Thanks @ditman

@ditman
Copy link
Contributor

ditman commented Feb 4, 2020

@amrfarid140 @collinjackson and I've been working on some extra changes to the branch throughout the day. There's one big change that we want to get in, though, which should simplify the FieldValues a little bit.

It is late here, but I'll get some stuff done tomorrow (I can prepare another branch/PR if you don't want to wait for that change)

@amrfarid140
Copy link
Contributor Author

@ditman Maybe it makes sense then to wait for you guys to finish all the changes before merging them to master

@ditman
Copy link
Contributor

ditman commented Feb 5, 2020

@amrfarid140 I think we're done! Take a look at the changes!

I've tested on my end and it seems to be working; but the more we test, the merrier.

Thanks for your patience!

@collinjackson
Copy link
Contributor

collinjackson commented Feb 5, 2020

@amrfarid140 Thank you SO much for the time you've put into this patch. I've been pairing with @ditman on this, and what our changes are doing is reducing fragility -- hiding classes and methods from the app-facing package if they're only useful to platform implementers, minimizing the platform interface surface area (making MethodChannel-related classes private), and ensuring that the platform interface classes that we think might change in the future extend PlatformInterface and use verifyExtends so that we can make changes without breaking platform implementers.

A few changes of note:

  • All *Platform classes are now hidden from the app-facing API.
  • FieldValue uses a static method on the platform class FieldValuePlatform to keep the exposed app-facing API minimal.
  • We don't think that it should be necessary to decode FieldValues except in unit tests so that code has been removed from the package. Hopefully this won't be a breaking change.
  • Web version now delegates to the native auto id generator.
  • Removed a confusing use of @visibleForTesting, relying on import visibility instead
  • Removed appName() in favor of app.name

Let us know if there's anything that seems off or confusing! I'm excited to see this landed.

@amrfarid140
Copy link
Contributor Author

@ditman @collinjackson Thanks so much for improving this PR. I've gone through the changes and all makes sense to me.

Everything is merged now to amrfarid140/master branch and both PRs have been updated.

@amrfarid140
Copy link
Contributor Author

Tests are failing on create_simulator.. we need to re-run them again and see what happens.

@collinjackson collinjackson self-requested a review February 5, 2020 15:38
Copy link
Contributor

@collinjackson collinjackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're working off an outdated version of the FlutterFire repo. You'll need to merge the upstream master before we can land this. Besides changelog there was one minor conflict (you had a different solution than @kroikie for #1859 and I think we should go with his version). I resolved it in a way that made sense to me; here is a branch showing that: https://github.com/collinjackson/flutterfire/tree/amr-master-merge

Merging this commit will resolve the iOS simulator failures: 16ed623#diff-0f7067c31caedf7df2739c9b07efa122

(The below comments were pending comments that I had on earlier versions of your patch, but I've left them here for posterity.)

///
/// Once committed, no further operations can be performed on the [WriteBatch],
/// nor can it be committed again.
class WriteBatch extends WriteBatchPlatform {
Copy link
Contributor

@collinjackson collinjackson Jan 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting this for posterity since you pushed back on my comment here earlier. What I was trying to suggest was following the same pattern established by Query, QuerySnapshot, separating the public API and method channel implementations. This enables the app-facing class to be extended in the future.


/// An interface for a factory that is used to build [FieldValue] according to
/// Platform (web or mobile)
abstract class FieldValueFactory {
Copy link
Contributor

@collinjackson collinjackson Jan 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case anyone is wondering why we do verifyExtends... previously this class didn't extend PlatformInterface, making it possible to use implements rather than extends on this class. This could lead to a situation where no new methods could be added to FieldValueFactory without breaking platform implementations. And this wasn't just a hypothetical concern, it happened in the web implementation.

https://github.com/FirebaseExtended/flutterfire/blob/b09cd242d1479d47e84b31265b6722f6ff35b95c/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel_field_value_factory.dart#L5

It's fixed now.

/// A CollectionReference object can be used for adding documents, getting
/// document references, and querying for documents (using the methods
/// inherited from [Query]).
abstract class CollectionReference extends Query {
Copy link
Contributor

@collinjackson collinjackson Jan 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I was trying to say here was that this class is tempting to implement using implements (and in fact the original PR https://github.com/FirebaseExtended/flutterfire/pull/1670/files#diff-167cff67d9c16a4fbee5de8f8a9cd33aR4) did so.

@amrfarid140
Copy link
Contributor Author

@collinjackson Merged that latest of flutterfire/master to my fork and updated both PRs. Not sure if your comments are based on old changes or the most recent ones.

Also not sure what's the issue with Android builds. Seems CI related rather than changes related. Would be great if you or @ditman can have a look. Thanks.

@ditman
Copy link
Contributor

ditman commented Feb 5, 2020

@amrfarid140 I'm relaunching the tests, they seemed to be temporary failures, unrelated to the branch. (Update: Everything is green now.)

@collinjackson collinjackson self-requested a review February 5, 2020 21:36
Copy link
Contributor

@collinjackson collinjackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ditman ditman merged commit 29eb495 into firebase:master Feb 5, 2020
@ditman
Copy link
Contributor

ditman commented Feb 5, 2020

Tagged v1.0.0, and published to pub.dev: https://pub.dev/packages/cloud_firestore_platform_interface/versions/1.0.0

@IchordeDionysos
Copy link
Contributor

@ditman @amrfarid140 May I ask why there is still a platform channel implementation in the cloud_firestore_platform_interface? 🤔

Is it to maintain backward compatibility until all platforms use the platform interface?
To me this is confusing... 😄
I would expect the platform implementation to throw an error that the current platform is not supported and that they can extend support themselves by implementing the platform interface. This would give a better error message than this #1972 and tell developers what's the underlying error. 🤔

@ditman
Copy link
Contributor

ditman commented Feb 24, 2020

@IchordeDionysos the MethodChannel implementation is the one used by the "native" platforms (ios/macos/android). Notice how that implementation extends its corresponding PlatformInterface, and is the default implementation.

Check the doc about plugin federation for much much more info!

@firebase firebase locked and limited conversation to collaborators Aug 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants