Multi-User Applications With PouchDB and IBM Cloudant
A simple solution for seamless synchronization of web application state in real time, using a NoSQL database hosted in the cloud.
Join the DZone community and get the full member experience.Join For Free
Imagine a web application used simultaneously by many users at the same time. It can become necessary to keep them in sync. We want to ensure that they all look at the same fresh data. We might want them to interact with each other. Think about co-editing of documents on Google Drive, chat applications etc. We’ve implemented a simple solution for seamless synchronization of application state in real time, using a NoSQL database hosted in the cloud.
The complete source code of the example application can be found at https://bitbucket.org/letsdebugit/synchronize-vue-app-instances-with-pouchdb.
A group of students of Royal Academy of Arts in Hague, Netherlands, recently asked me to help with their ambitious study project. Amongst many features, they wanted to have real-time interactivity. Visitors would interact with the website and see actions of other users at the same time.
Project mentor has suggested vanilla JS and rolling out an API with a web-socket server. This seemed too complicated. Brilliant artists as our students are, they’re not IT professionals. I proposed a simpler solution:
- Use a lightweight web framework, to simplify code and get good control of application state
- Automatically synchronize the state between the running instances, using an off-the-shelf NoSQL database in the cloud
We’ve quickly settled down on the following:
- Vue JS for front-end, as it’s simple and it can be pulled from CDN, without any build process
- PouchDB - in-browser CouchDB instance with automatic synchronization to a remote database
- IBM Cloudant - a free CouchDB database in the cloud
With this intriguing technology stack we were able to roll out a working chat application within one hour, for the starters. This was just an example which will serve them as a boilerplate for all other types of interactions. Below we discuss how it’s been made.
Architecture for state synchronization between application instances is very simple:
All data is loaded, edited and saved only to the local PouchDB database (which internally uses browser’s IndexDB storage). PouchDB database takes care of bi-directional synchronization with the master database in the cloud - there’s no need to write any code for it!
We’ve subscribed to IBM Cloud and added Cloudant service instance under free tier. We went to the Cloudant Dashboard and created a new empty CouchDB database named
cloud-chat. As recommended by IBM, we created a partitioned database, where document identifiers will be prefixed with type, for example
message:9820981390812398. This is supposed to give much better performance and lower the costs, should the application ever go commercial:
In Cloudant Account Settings we’ve changed CORS settings to accept requests from all domains, as pictured below. Warning! This is OK for development, but for production you should only allow requests from your website domain!
Now you need to create access credentials for the database. Go to Cloudant service instance, Service Credentials and click
New Credential. Give it a name, select
Writer role and press
ADD. Credentials record is now created. Expand it to see your user name, password and the URL of your Cloudant instance. Take note of them, you will need them in your code to create URL for connecting to the database.
To run the code, you need to provide your own Cloudant credentials in database.js file.
Warning! In production application we wouldn’t use this URL directly from client code, because your credentials are at risk. We would rather proxy calls through a web server where the UI application is hosted, or use other ways of securing access to your online database.
Connection to a local PouchDB instance is simple. We instantiate
PouchDB object with a database name. In a similar fashion we connect to master database in the cloud - using URL obtained from IBM Cloudant dashboard. Then we instruct the local database to stay in sync with the remote database:
Loading the chat history requires one call to PouchDB and a bit of mapping and sorting. Just remember that messages are always retrieved from the local instance! There is no need to reach to the remote instance. Local database will be automatically synchronized with the remote database in a very efficient way.
Notice how we specify document key prefix
message: when fetching data. This is to prevent fetching other types of records. Our database might contain more than just chat messages after all!
Saving messages is done with
put() to the local database. Local database will automatically send these changes to the remote database. Other connected applications will soon receive notification about these changes and will update themselves.
The VueJS chat application does the following:
- User enters his nickname and proceeds to chat window
- Chat history is loaded from local database
- Users enters messages and submits
- Message is saved to local database
- Local database synchronizes itself with master database
- Other application receive changes from master database and update their UI
For brevity, we’ve removed all non-essential things from the code snippet below. Please refer to the git repo for the full source code:
index.html using a web server of your choice and voila, we have a multi-user chat application running on IBM Cloud!
The article is also available at my blog Let’s Debug It.
The complete source code can be found at https://bitbucket.org/letsdebugit/synchronize-vue-app-instances-with-pouchdb. Feel free to clone and reuse this code. Any suggestions or questions are most welcome!
Published at DZone with permission of Tomasz Waraksa. See the original article here.
Opinions expressed by DZone contributors are their own.