Skip to content
James edited this page Nov 23, 2016 · 12 revisions

Welcome to the post-its wiki!

Vue.js & Websockets Demo App

So I set myself a little challenge to get a basic Vue.js app working, with persistence (probably to mongo) and real-time comms via web sockets, the application will be a basic note taking app where users can see who else is online and making notes, and possibly even collaborate on the same notes, depending how far I get and how hard it turns out to be!

The steps I've undertaken to get here are below (with some estimates of time taken for reference) before we get into that I wanted to jot down some thoughts on the task and the process;

  • Vue is lovely, I've not used it before but I can see it's potential, our team assessed Vue vs React and picked the latter for a rewrite of our SPA based on its maturity, contributors, and adoption, but we could easily have picked Vue.

  • I have used the boilerplate vue-cli project from the official VueJs templates, I have not used webpack before so I need to spend some time understanding the dev setup, but it just works out of the box which is nice. The hot reloading is especially good.

  • On that note, I have manually pulled in bootstrap CSS and fonts for some styling tweaks, which is probably entirely wrong as I have circumvented webpack. If I had more time I would learn how to do this properly.

  • The tests do not run, again with more time I would like to get at least some form of unit testing in place.

  • The example I based the SPA off uses native JS for things like array manipulation, for example, I would like to pull in underscore or lodash to help with these operations although not strictly necessary, with hindsight perhaps it's better to restrict the number of libraries we rely on, though, up for discussion I guess

  • There is no routing in place, the app is served on the root, if we were to build out the application we would need to set up routing as the functionality grows

  • During development I spotted the odd message sent to the socket server of 'Test text', my code handled this but unsure where this was coming from, I was using a demo socket server initially until I got my own running so perhaps another app was pinging that whilst I was working, or it was the ghost in the machine.

  • I have not implemented explicit closing of connections, nor an accurate connection status of users, I do have a list of connected users but this is created as users connect and is not actively maintained (other than when closing your connection, others see you disappear from their connected user list). This missing functionality was purely down to time, it would be nice to show status against the usernames on individual notes.

  • I have implemented my own socket server, now when the client connects it sends its user and any local notes it may already have (from local storage) to the socket server, this in turn stores this data (initially in memory cache but eventually will be to a database/document store) and then broadcasts all users and notes back to everyone.

This is a bit heavy handed but it means that everyone gets updated, each client handles the messages appropriately and stores in its own local storage, thus completing the sync.

This now mitigates the client side distributed sync I had previously that had a problem where system notes would have been lost forever when everyone was offline, or if everyone cleared their local storage.

Now as long as the socket server remains up and it's memory cache intact the system state is preserved. Proper redundancy can be achieved via storage to disk, either a database or document store such as Mongo, given the time.

  • A race condition exists on the edit of the same note by two (and presumably more) users, the last user to save receives a duplicate that is never synced to the other user's notes, due to the way I have written the logic. This could be solved by locking the notes upon edit and propagating the lock. So only one user can edit one note at a time, upon saving the note would be unlocked and the note could be edited by another user and start the cycle again, this feature is a trade-off of time vs value, for a production system this is a must have, for a demo project at least we are aware of it and can decide on time vs value to fix/implement.

  • One thing I found when developing the socket server and connecting to this is that in my implementation (hosted in Heroku) I need to leave the port number off the address that the client app uses to connect, a minor point but it caused a bit of pain.

  • I initially created my repository in bitbucket, so have moved over to GitHub but in so doing may have mangled my commit history! I've pushed all my local branches to this new remote and continued work from here so you can see the branches and how I've broken down the tasks as per the summary below.

Questions & Answers

  1. What was your reasoning for implementing the solution they way you have?
  • Having never used Vue or Websockets I decided to use a template project and learn the fundamentals to get a working prototype running, and then research and implement communication via the socket server provided. I made a choice not to test drive the development due to time constraints as I needed to learn a new framework and create a running application in a relatively short space of time.
  1. How would you manage users going offline and online?
  • We could periodically attempt to ping the socket server or another remote endpoint and use the response from this to indicate connection status. Once we know that we can use local storage as our cache of unsynced changes and when a connection is available after a period of being offline we could send up unsynced data
  1. How would you manage allowing users to continue editing and adding notes when in offline mode and then syncing when they come back online?
  • Answered above, if the user is offline then do not send messages to the socket server, just mark content as unsynced and store locally until later, then send and mark as synced when online
  1. How would you manage conflicts between edits made by different users to the same note?

There are several approaches we could take to this;

  • We could either give precedence to the last change seen.
  • We could agree on a rule that the creator always overrides others in the case of a conflict.
  • Or my preferred solution (and one which would mitigate the race condition duplicate note scenario described above) is to mark a note as locked when a user starts to edit, propagate that lock to all other users and ensure the application does not allow a user to edit a 'locked' note. Upon saving of the locked note we could clear the lock, propagate this via the server and allow other's to edit.

Summary of steps taken, with time spent

2 hours:

  • Set up repo and boilerplate Vue app
  1. http://vuejs-templates.github.io/webpack/
  2. Followed installation and getting started notes
  • Implemented vuex for store/persistence
  1. https://www.npmjs.com/package/vuex
  2. Addition of store and basic components from to do list tutorial can now add, edit, complete and remove todos
  • Refactored components from todos to notes
  1. merged vuex branch up to develop created a new branch from develop called todos-to-notes
  2. refactored todos to notes
  3. added created date, and filter using moment to display it
  4. updated styling/layout
  5. added basic validation of note description
  6. merged todos-to-notes up to develop

1 hour:

  • Implemented local storage of notes
  1. created a new branch from develop called local-store
  2. allocate guid to the user, store locally, along with notes - http://guid.us/GUID/JavaScript needed some form of id, pseudo guid, used this and translated into ES6 syntax
  3. rehydrate app from local storage on start/page reload
  4. persist add, edit and remove in local storage
  5. persist archival of notes in local storage, using the newly added identifier to find and update the archived note

3 hours:

  • Implemented use of web socket server
  1. read up on web sockets
  2. implemented basic connection
  3. new branch sockets created for this part of the build
  4. allocated user an identifier for reference
  5. show user id against notes
  6. send a message to socket server whenever there is a change to user's notes (add, edit, archive or remove)
  7. process received messages from socket server informing of another user's note changes
  8. show other user's notes
  9. List of other connected users (Connection status, only set upon connection, not updated/maintained so inaccurate)

1 hour:

  • Implemented in memory storage on web socket server
  1. created my own socket server based on the example and further research due to deployment challenges!
  2. added unique legible user names to SPA interface, courtesy of: https://jsfiddle.net/katowulf/3gtDf/

2 hours:

1 hour:

  • created arrays of users and notes in memory using node-cache
  • ensured that on client connect the user and local notes are sent to the server for sync to other connected clients

TODO

Estimate 2-3 hours:

  • Implement persistent (to disk) server-side storage