Posted in 2017, Lightbeam, Outreachy

Lightbeam – ‘tale of 2 stores’

Thanks to Bianca, my fellow Outreachy-Lightbeam project partner for coining the above title in her blog and asking me questions to explain about the bug(PR) I recently fixed for Lightbeam. I  started explaining her last evening via quick diagrams and I already had an idea to make my next blog post colourful 😉

I have been inspired by Lin Clark’s code cartoons and Mariko Kosaka who always draw and make technical reading fun! Here is an attempt to write a post and explain Lightbeam’s store architecture via diagrams 🙂

To revamp Lightbeam into a web extension we decided to follow the following architecture:

20170623_125927

A web extension consists of a collection of files and we employed the following directory structure to achieve the above architecture:

20170623_125810

We were able to chalk out an MVP soon, everything behaved as expected, until we found this bug.

  • Open Lightbeam
  • Open console
  • Clear the storage manually through the console: browser.storage.local.remove('websites').then(()=>console.log('removed')).catch(err=>console.log(err))
  • Also set store._websites=null manually through the console
  • Refresh the page – graph disappears
  • Refresh the page again, graph appears with old values

Thanks to Jonathan for pointing out that there were two store instances created and thus began – ‘tale of 2 stores’.

Following was the code implementation to achieve the above architecture:

The problem with this approach was that store.js file was loaded from two different places and that’s how we ended up having two store instances.

In other words, this was the problem:

20170623_130426

Now to debug the above specified bug:

  • capture.js had one store instance because of store.js loaded via background script
  • lightbeam.js had another store instance because of store.js loaded via the script tag
  • index.html page was loaded and lightbeam.js got the required websites to display via getAll() from it’s store instance
  • Next, web extension storage was manually cleared via browser.storage.local.remove and store._websites was explicitly set to null
    • in the first page load, there was nothing to display because the getAll() returned nothing from it’s store instance (because of the above manual deletion)
    • on second page load, capture.js had done a setFirstParty() call to it’s store instance which in turn wrote to the browser.storage.local.set
      • capture.js is triggered when a tab (re)loads
      • capture.js‘s store instance had its copy of _websites already populated (when the manual store._websites=null was done, it was done on lightbeam’s store instance) and setFirstParty() used this already populated _websites value and wrote to the browser.storage.local.set
  • This is how the visualisations appeared back on the second page load

To fix this bug, we now have storeChild.js which acts as an interface, or is the only point to talk to the background store.js. With the child and parent architecture, the parent will always be in charge of when the write happens and so will serialise the writes which will behave like a locking database.

20170623_130453

The page script storeChild.js talks to the background script store.js via message passing.

Advertisements

Author:

Technology and start-up enthusiast. JavaScript is my second love, food comes first ;). Love coding, attending technical conferences, learning new things and meeting new people.

One thought on “Lightbeam – ‘tale of 2 stores’

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s