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

feat(reducers): cache reducer for increased performance - @puppybits #335

Merged
merged 148 commits into from Nov 23, 2021

Conversation

puppybits
Copy link
Contributor

This fixes massive performance issues we had using both Firestore & redux-firestore in production. Running a transaction update must round-trip to the server before being reflected in Redux. The mutate + cache reducer allows changes to be reflected in redux synchronously with no additional work.

There are no breaking changes. But it does adds id & path properties to all results. Mostly it add the new cache reducer for synchronous optimistic updates. And it adds a new mutate function which the cache reducer uses to reflect changes synchronously.

  • New unit tests for cache reducer & mutate all pass.
  • Numerous performance tuning done on the cache reducer for large, complex datasets.
  • Handles firestore rejects & offline saving (via onSnapshot.includesMetadataChanges)

Description

  • Cache Reducer. UI feels instantaneous to users.
    • Enables synchronous optimistic updates for new, deleted & updated data.
    • All data changes synchronously reflected in the cache reducer queries.
    • Once Firestore approves/rejects a change it also removes the optimistic commit.
// selector for cache reducer
(state) => state.firebase.firestore.cache[myStoreAs].docs;

// access a read-only fragment of Firestore based on all active queries
const document = state.firebase.firestore.cache.database[full_path_to_collection][document_id];
  • Mutate. Simplifies saving, batching and transactions.
    • Easily switch between single saves and atomic transactions.
    • Simplifies complex saves that have to coordinate through multiple redux actions.
    • Synchronously updates queries in the cache reducer for the UI to feel immediately responsive to all changes.
// single save
getFirestore().mutate({collection: 'tasks', doc: 'task-1', data: {status: 2}});
// batch
getFirestore().mutate([
  {collection: 'tasks', doc: 'task-1', data: {status: 2}},
  {collection: 'tasks', doc: 'task-2', data: {status: 2}},
]);
// transaction, read results use dependency injection for write functions.
getFirestore().mutate({
  reads: { task1: {collection: 'tasks', doc: 'task-1'} },
  writes: [ ({task1}) => ({collection: 'tasks', doc: task1.id, data: { status: task1.status +1 })) ]
});

Check List

If not relevant to pull request, check off as complete

  • All tests passing
  • Docs updated with any changes or examples if applicable
  • Added tests to ensure new feature(s) work properly

Relevant Issues

Bobby and others added 30 commits February 25, 2021 16:37
chore(cache-reducer): include id & parent path as prep work
This effectively deprecated the need for both the dataReducer and the orderedReducer. The cache reducer also moves the populate functionality to run when the action is triggered, instead of in the selector. It also adds a 'fields' property on the query to reduce react over-rendering by ignoring unused data in the view.
feat(cache-reducer): added new reducer for instant mutation changes
…ux-firestore into feature/immediate-mode-mutate
feature(immediate-mode): support for custom firestore.mutate with cache reducer
@prescottprue prescottprue changed the base branch from master to v0.16.0 November 23, 2021 05:43
@prescottprue prescottprue changed the title Big Performance Improvements feat(reducers): cache reducer for increased performance - @puppybits Nov 23, 2021
@prescottprue
Copy link
Owner

Thanks so much for these amazing changes, the tests, and keep an eye on keeping changes backwards compatible - apologies it took so long to get these in. Cycles should be shorter moving forward

@prescottprue prescottprue merged commit daefa10 into prescottprue:v0.16.0 Nov 23, 2021
@prescottprue prescottprue mentioned this pull request Nov 23, 2021
3 tasks
@prescottprue
Copy link
Owner

I've noticed a few things which I addressed including eslint warnings/errors.

Working on cleaning up in the v0.16.0 PR before releasing which includes

  • adding back removed reducers - these can be deprecated if we really think they should be removed
  • removing the performance util - want to make sure we can have this in without impacting bundle size as much for production build
  • removing debug - adding a debug/log util was planned to happen all at once after a bit of research. Debug dependency adds size - we can do this separately (your changes which log whats happening clearly will be revived once this is done)

One of the new tests is failing though, so I'll need to debug a bit more: https://github.com/prescottprue/redux-firestore/runs/4296991419?check_suite_focus=true#step:6:423

@prescottprue prescottprue mentioned this pull request Feb 26, 2022
3 tasks
prescottprue added a commit that referenced this pull request May 1, 2023
…431)

* feat(reducers): cache reducer for increased performance - @puppybits (#335)
* feat(core): add mutate method for easier transactions - @puppybits 
* feat(core): add lodash module replacement webpack plugin - @puppybits 
* feat(core): replace uglify webpack plugin with terser webpack plugin - @puppybits 
* feat(build): add `firebase/firestore` as a webpack an external (improves UMD bundle size by not including Firestore SDK bundle)

BREAKING CHANGES
Firebase peer dependency now set to ^9 (previously ^8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants