Offline application using CouchDB / PouchDB for synchronization along with DDD/CQRS in the backend

260 views
Skip to first unread message

Christian Droulers

unread,
Jan 26, 2018, 2:02:43 PM1/26/18
to DDD/CQRS
Hello people! Been following all messages on this list for a while, always interesting to read and helps a lot with the current project I'm working on.

Right now, my architecture is fairly straight-forward. The frontend is React / Relay going through a GraphQL server in .NET Core. The GraphQL server queries a SQL Server read model which is updated via Event Listeners dispatched by a simple DDD/CQRS implementation in C#. GraphQL Mutations just use the Repository to load an Aggregate Root, modify it, then save the resulting events, which are dispatched using a bus.

This works quite well right now and I've been able to easily create a few new read-models as well as new listeners for different business requirements!

Our next step is offering a version of the web app that is offline compatible. The domain is basic Healthcare case communication (doctor A needs help from specialist B, sends case with data, files, etc., specialist answers with data, files, etc. Notifications and validations ahoy).

I've looked at multiple options for different possibilities and I'm now a bit stuck on where to go next and what to choose.

I'll try to list my thoughts and see what all y'all think.

Option 1:

Use existing GraphQL architecture and add a better layer of caching / optimistic responses. Apollo Client 2's architecture (with multiple links) would allow a decent way to work with that.

  - Use the "refetch" features to regularly refetch the queries that have been loaded so while we are online, we get fresh data.
  - Make sure all mutations have optimistic responses so we can modify or create cases without going to the server and let the Apollo link send the mutation when connectivity is back, handle conflicts.
  - This implies very few changes on the server-side since the offline handling will be fully done on the client-side.
  - Also means that the client-side interface will have to sometimes tell a user it can't work while offline for certain features because of missing data, which could be acceptable depending on what level of effort we put in pre-fetching data.
  - Service Worker could easily help here for background synching since it could regularly poll the server for "reference" data.

The major problem I see with this is that the local offline cache will never have more data than what the user has loaded unless I start making regular background queries hoping to get enough data to have a fuller experience. For example, loading multiple "pages" from the main dashboard's list of cases so the user can page through cases even when offline.

Option 2:

Using a technology like CouchDB paired with client-side PouchDB where each user has a CouchDB database with all the necessary data that is kept up-to-date on the server using Event Listeners.

  - It means that for every CQRS event dispatched, I'd have to look up which users are affected and update each database separately. CouchDB boasts that it's not a problem to have thousands of databases, so that's ok. I can also rebuild the user databases asynchronously and swap them out if I need to.
  - Once the initial synchronization is done for a user on the device, it is then fully offline capable, as all reference data necessary is available!
    - Would need some tests to see how large a user database can grow, there is already a concept of archiving for cases, so the user database could be kept smaller using that concept and while offline, archived data is not available. Same with attachments!
  - My bigger concern is how to handle the user's action affecting the event source. My basic understanding now is that the web app would update the PouchDB, which would sync to the CouchDB server, then a process would subscribe to the "_changes" feed of each user database.
      When an change is marked as a user's action, we then try to transform that change into a command, execute it and let the data flow through the bus to all the other databases.

The offline need comes from the fact that a lot of users are located in the Great North of Québec (Canada) and have spotty and slow Internet connections. Allowing them to create a case even when their connection is not working would mean the world to them!

We also have more and more mobile users, which also don't always have fast connections.

Using the browser with recent features as the deployment channel for the app is so far the easiest and I hope everything can work.

I'm looking for input on any of all the points I've listed and possibly ideas outside of the box! I might be heading in the wrong direction!

Thanks for your time!
Reply all
Reply to author
Forward
0 new messages