How to migrate out of date, persisted NgRx state - ngrx

I'm looking to persist the application NgRx store to either local storage or a NoSQL database. This is so the application/user can resume from where they left the application last time they visited.
However, if the structure of the state has changed in my application the old persisted state will need to be migrated to the current one. Is there a way to do this with standard NgRx tooling or features or another popular pattern/method?

There is no generic way as far as I know, it's up to you to handle structure changes - we can't make those decisions for you.
The answer also depends on what you store, is it the full state or are you storing the actions. Both are valid and serve different needs.
If you're storing the full state, you'll have to provide a migration to migration from version 1 to version 2.
If you're storing actions, you'll have to keep the reducer functions to handle those actions.

Related

Using Redux or not for filter options

I'm very new to React Native (did some courses) and now building my first app on my own which is going great, but I need some advice regarding user applied filters and how to handle this.
Quick summary of what needs to be done.
The user should be able to set some filters so only certain data is displayed and this state is saved even after closing the application, user logs in again and still sees only the data that is filtered because of the filter option he/she set before.
In one of my courses I got an introduction into Redux and my question here is should I use Redux for this feature or maybe Context for this ? My data is fetched from Firestore and I'm able to use a query to filter data from firestore but that just ends up in many read/writes which cost money.
All advice is more than welcome!
use redux
when you need some static state globally in your app then use context like open close drawer etc. For dynamic states go for redux
As mentioned in stackoverflow answer :
As Context is no longer an experimental feature and you can use
Context in your application directly and it is going to be great for
passing down data to deeply nested components which is what it was
designed for.
As Mark Erikson has written in his blog:
If you're only using Redux to avoid passing down props, context could
replace Redux - but then you probably didn't need Redux in the first
place.
Context also doesn't give you anything like the Redux DevTools, the
ability to trace your state updates, middleware to add centralized
application logic, and other powerful capabilities that Redux enables.
Redux is much more powerful and provides a large number of features
that the Context API doesn't provide, also as #danAbramov mentioned
React Redux uses context internally but it doesn’t expose this fact in
the public API. So you should feel much safer using context via React
Redux than directly because if it changes, the burden of updating the
code will be on React Redux and not you.
It's up to Redux to actually update its implementation to adhere with
the latest Context API.
The latest Context API can be used for Applications where you would
simply be using Redux to pass data between components, however
applications which use centralized data and handle API requests in
Action creators using redux-thunk or redux-saga still would need
Redux. Apart from this Redux has other libraries associated with it
like redux-persist which allows you to save/store data in localStorage
and rehydrate on refresh which is what the Context API still doesn't
support.
You can refer to the blog1 and blog2 in order to get more clarity on when to use redux and context.

Best practices for migrating to a new data model when working with a Cloud Firestore backend

The problem is as follows. We have 2 native apps (ios and android) connected to a Firestore backend. Our current data model stores the information about the users spread across 5 different collections (profile data, user answers, user legal documents, etc). This means, often times, when we need to query data about the user we need to make several queries and manually join them together to get what we need. It’d be much simpler for us to have all the information stored in a single collection. This is a problem we have now, and as our business will continue to evolve, we will have more situations where we need to change the structure of the data model.
Currently, we use the Firestore API to query the user’s data in the frontend to have real-time updates. ATM we don’t use custom endpoints and therefore we don’t have any kind of versioning in place.
Are there any best practices or strategies to perform such a data model migration without forcing the user to upgrade to the latest version of the app?
We can think of some solutions:
Use versioned-endpoints and forget about real-time updates (decouple the FE from the BE)
Migrate the current data to the new data model while keeping the old collections still actives to serve old versions of the app. Additionally, write some cloud function listeners to keep the 2 models in sync (whenever an old version of the app writes in any of the 5 user collections, copy that data to the new data model)
...
…
The problem of an evolving data model and having several FE’s consuming the data is extremely common. The normal best practice would be to have a versioned endpoint that the FE communicate to, to break the direct dependency on the data model. However, it doesn’t seem like Firebase have a set best practice for this. This sounds a bit strange to us, as it is such a common problem to have, and that Firebase solves so many other common challenges out of the box.
What are we missing?
Related questions:
https://www.reddit.com/r/Firebase/comments/dyhzlv/best_practices_of_versioning_with_a_firestore/
Thanks!

Do we really need Vuex when building a web app using Firebase + Vue?

We are building a to-go order web application for restaurants with Firebase and Vue.
Restaurants can create their own pages, and add menu items.
Users (customers) can orders some foods from those restaurants pages, and pick them up later.
At the beginning of the project, we have chosen to store some transient data (user data, shopping carts, etc.) in the Vuex store. It works fine but there are a lot of complexities in it, which made it hard to maintain.
Recently, I have realized that we could just use Firestore for those transient data as well, which will greatly simplify the architecture, eliminating Vuex completely.
Before making all the changes, I want to make it sure that I am on the right track and I am not missing anything.
I'd really appreciate any comments and suggestions from those people who have experience in building relatively large scale web applications using Firebase + Vue (or even React).
Short Answer
Yes, this seems perfectly reasonable.
Long Answer
Many web applications have their state synchronized via an external service like Firebase, GraphQL, etc. In these cases you may already be using some kind of shared, UI-independent cache (e.g. Frestore, Apollo client). Unless the aforementioned cache cannot be easily accessed by your UI components, there would be little benefit to switching or duplicating the data to Vuex.
Keep in mind that even in the above scenario, Vuex can still be a useful tool to track UI-specific state across otherwise disconnected components in your interface. For example, you could globally identify the user's current viewing mode, or which modal is open.
Yes you can go without VUEX, however, it will limit your potential.
First of all vuex is really simple, you can easly add vuex your code.
Without Vuex you may write same code again and again.
For example you want to redirect your user to his restaurant page when he logs in. So you write a code that first checks if user has a restaurant and then gets his restaurant ids.
Also you want to check when a user opens a restaurant page, if the user owns that page, you write the same code again. However, if you have a function that returns a value if user is the owner or not. You can call it any page you want.

Is Redux secure?

I'm learning Redux and I can see people storing all kinds of information into the state and doing all kinds of different operations through reducers. But is Redux secure or is there any known vulnerabilities of using Redux? If there are then are there any best practices that I can follow to secure the state?
Maybe let's change the question - does keeping any data in the client side is safe? And answer is no. Any kind of secret data should never exist in the front side. State management system will not change the app security. Even if you have encapsulated state the data can be catched by watching the network and data coming to the browser or by traversing html because most of the data in the front side is just used in the view. So, really any kind of data which gets to the browser should be considered as fully transparent and only the backend can really secure what is given and what not.
Is it not a good idea to save passwords and sensitive information in your redux store. When you go into production, definitely turn off the redux-devtools setting because if you don't then anyone can see your whole application state with the chrome extension (if you care about hiding your app state). You have to be especially careful if you are syncing your state to something like local storage as well. In general, send passwords or sensitive info right to the server in an encrypted fashion.

Is DynamoDB streams the right option for this use case?

I have a DynamoDB table that contains key value pairs that will be read by a number of applications. On startup each application will read the entire table and cache it in-memory.
The problem I'm trying to solve is that of getting the applications to update their cache if one or more items in the DynamoDB table have been modified.
DynamoDB streams initially seemed to be the right approach to solving the problem. I have implemented the consumer using Kinesis Client Library (KCL) as recommended by AWS. While implementing it, however, I have encountered some problems that make me believe that I'm on the wrong track. Specifically:
When I create a new consumer using KCL, it creates a new DynamoDB table to do the housekeeping of leases and checkpoints, such that when the application is restarted, KCL knows which records have been consumed and which have not. This is not what I need for this problem. Any stream records that are created while the application is offline is irrelevant, since the entire table is read upon application startup.
Several instances of the same application are running at the same time. Each of them needs to be notified of table updates. To implement that in KCL I need to assign a unique application name to each of them. Otherwise they will share the lease table and only one of the applications will get notified. One table for each application instance doesn't seem right. Also I would then need something to remove unused tables.
I also implemented it using the low level API instead. That works fine when there's a single shard. My implementation doesn't handle re-sharding like KCL, however, so it's too fragile. It seems wrong to have to implement handling of re-sharding for the simple problem I'm trying to solve.
I'm beginning to consider other solutions like:
Implementing a lambda function that gets triggered on updates to the table. The function sends a notification to an SNS topic. Consumers create SQS subscriptions on the topic and gets notified via that. This solution has too many moving parts for my liking.
Make the applications periodically re-read the entire table and determine themselves if changes have been made. This solution feels a bit primitive, but seems to be the simplest.
All solutions that I have considered so far have quite significant drawbacks. What am I missing?
It depends on how your KCL is pushing to the dependent apps but
I believe the SQS path is the correct choice.
You can add a presumably infinite number of consumers without being throttled.
When you do add another dependent app, it won't require changing your KCL to push to it, the new app will simply watch the SQS queue.
You gain the ability to monitor the queue when issues happen.
More moving parts to setup, but once you have the Streams -> SNS -> SQS pipe in place, it's basically bulletproof.
Just my 2¢.
Nowadays an AWS AppSync GraphQL API with subscriptions may be the simplest approach to power this type of application, with the least number of moving parts.
Whenever one of your applications starts up, it connects to your AppSync GraphQL API using the Amplify framework or AppSync SDK and subscribes to the updates its interested in. Then whenever an application updates information in the table via your GraphQL API, all your other applications will be notified of the change, along with the relevant changed data.
AppSync integrates well with DynamoDB out of the box, allowing you to generate DynamoDB tables with appropriate indexes alongside your GraphQL or generate GraphQL from your existing DynamoDB tables if you so choose. Amplify can even help you automatically generate an AppSync GraphQL API at a higher level with associated DynamoDB tables, indexes, entity relationships, and more like elasticsearch search capabilities by using their GraphQL transformers.

Resources