Skip to content

Remove cyclic references in RemoteDocumentCache #3857

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 7 commits into from
Oct 1, 2020

Conversation

schmidt-sebastian
Copy link
Contributor

@schmidt-sebastian schmidt-sebastian commented Sep 28, 2020

This PR removes a static inheritance that WebPack cannot tree-shake.

Before, our RemoteDocumentCaches would look like this:

class XYZRemoteDocumentCache {
static class XYZRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {...}
}

This patterns breaks code optimization in Webpack (as per @Feiyang1's research), but it does allow us to access "private" members within the enclosing class while also extending from another class. To address the Webpack issue while keeping some of the encapsulation, I:

  • Extracted the XYZRemoteDocumentChangeBuffers into top-level classes.
  • Changed XYZRemoteDocumentCaches to XYZRemoteDocumentCacheImpls
  • Made XYZRemoteDocumentCacheImpls methods public, so they can be used by the newly extracted types

The rest of the repo still refers to the old types, which are now interfaces and hide the new public methods. This is the same pattern that I applied in lots of other places already (see LocalStore), and it also allowed me to make two functions tree-shakeable that are only used in Multi-Tab (getNewDocumentChanges() and getReadTime()).

There are no logic changes.

@changeset-bot
Copy link

changeset-bot bot commented Sep 28, 2020

⚠️ No Changeset found

Latest commit: 122362f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Sep 28, 2020

Binary Size Report

Affected SDKs

  • @firebase/firestore

    Type Base (d4db75f) Head (446954f) Diff
    browser 249 kB 249 kB +69 B (+0.0%)
    esm2017 196 kB 197 kB +129 B (+0.1%)
    main 483 kB 484 kB +448 B (+0.1%)
    module 247 kB 247 kB +69 B (+0.0%)
    react-native 196 kB 197 kB +129 B (+0.1%)
  • @firebase/firestore/exp

    Type Base (d4db75f) Head (446954f) Diff
    browser 189 kB 189 kB +129 B (+0.1%)
    main 477 kB 477 kB +448 B (+0.1%)
    module 189 kB 189 kB +129 B (+0.1%)
    react-native 189 kB 189 kB +129 B (+0.1%)
  • @firebase/firestore/memory

    Type Base (d4db75f) Head (446954f) Diff
    browser 187 kB 187 kB +16 B (+0.0%)
    esm2017 147 kB 147 kB +20 B (+0.0%)
    main 357 kB 357 kB +162 B (+0.0%)
    module 185 kB 185 kB +16 B (+0.0%)
    react-native 147 kB 147 kB +20 B (+0.0%)
  • firebase

    Type Base (d4db75f) Head (446954f) Diff
    firebase-firestore.js 287 kB 287 kB +33 B (+0.0%)
    firebase-firestore.memory.js 227 kB 227 kB -2 B (-0.0%)
    firebase.js 831 kB 831 kB +33 B (+0.0%)

Test Logs

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Sep 28, 2020

Size Analysis Report

Affected Products

No changes between base commit (d4db75f) and head commit (446954f).

Test Logs

* The RemoteDocumentCache for IndexedDb. To construct, invoke
* `newIndexedDbRemoteDocumentCache()`.
*/
export class IndexedDbRemoteDocumentCacheImpl implements RemoteDocumentCache {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can "export" be removed from the declaration of IndexedDbRemoteDocumentCacheImpl? It doesn't appear to be used outside of this file and its name implies that it is an implementation detail that should not be exposed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The entire idea behind the XYZ and XYZImpl is that XYZImpl is not exported, so that the public fields in XYZImpl are only visible within the module. So, yes, this should not be exported.

* The RemoteDocumentCache for IndexedDb. To construct, invoke
* `newIndexedDbRemoteDocumentCache()`.
*/
export class IndexedDbRemoteDocumentCacheImpl implements RemoteDocumentCache {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should IndexedDbRemoteDocumentCache implement IndexedDbRemoteDocumentCache instead of RemoteDocumentCache?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Thanks for catching.

* The memory-only RemoteDocumentCache for IndexedDb. To construct, invoke
* `newMemoryRemoteDocumentCache()`.
*/
class MemoryRemoteDocumentCacheImpl implements RemoteDocumentCache {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should MemoryRemoteDocumentCacheImpl implement MemoryRemoteDocumentCache instead of RemoteDocumentCache?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Thanks for catching.

indexManager: IndexManager,
sizer: DocumentSizer
): MemoryRemoteDocumentCache {
return new MemoryRemoteDocumentCacheImpl(indexManager, sizer);
Copy link
Contributor

Choose a reason for hiding this comment

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

TypeScript noobie question: How does this compile since MemoryRemoteDocumentCacheImpl does not implement MemoryRemoteDocumentCache?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TypeScript interfaces are enforced by duck-typing - if a type happens to implement all members of an interface, it is considered identical to a type that explicitly implements the interface. Explicitly implementing comes in handy when the methods are renamed or added as it will produce much saner errors.

@schmidt-sebastian schmidt-sebastian merged commit 34c8693 into master Oct 1, 2020
@schmidt-sebastian schmidt-sebastian deleted the mrschmidt/roc-easy branch October 1, 2020 17:44
@firebase firebase locked and limited conversation to collaborators Nov 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants