Scaling: The Final Question. Performance and Load Testing: The Answer

04 January 2017

Spree E-Commerce For Ruby on Rails

Back in my days at a student, one of my networking professors brought up the same point every time we’d meet for a class: “When you’re implementing something, always ask yourself, ‘How does it scale?’” Over the last few months I’ve spent a lot of time dealing with systems and making sure they scale well using various technologies. I ran into an unexpected on today, though. It was Spree. Yes, the extremely configurable and awesome e-commerce platform does not play well with certain scenarios.

The issue was that whenever an of an order was updated which altered shipping costs, a callback chain was invoked. This either creates or updates shipping information for each item being ordered. What this means for the application is that (in order to remain highly configurable and track everything perfectly) each individual item from an order has a ShippingItem in the database. Buy 10 widgets, you create 10 ShippingItems. Buy 1000 widgets (or even 200), and Heroku will throw H* timeouts, which introduces [other errors with your Spree Addresses] that have to be solved so your users can view in progress orders and continue the checkout process.

The unforunate effect of this is that the more items someone wants to order from your site, the slower it will run. To throw some numbers in, an order with a total quantity of 2000 items took approximately 2 minutes to update the user’s address during the order process on a 1x Heroku dyno. The saving grace here is that the Spree team keeps a Slack channel open, and @brendan was able to point me to a previous issue and fix over at the Spree Github. Even better, dropping it in worked like a charm. Now, it has introduced a few more complications, such as needing to update a handful of template files and adjust a little logic, but in the course of an hour we had large orders running through the customer’s system again.

The point of this post isn’t to point out any weaknesses on Spree’s part, but to highlight the importance of making sure your systems scale. “Your” involves not just the code you write, but also other code being included. More importantly, make sure to test it on a system identical to your production environment. The reason I say that is I’d run many test orders through the system, but had only ever ran large orders through locally, assuming that it wouldn’t make a difference. I’d even noticed the substantially large amount of SQL queries for the checkout process on the area that had ended up hanging. What was different though was that on my development machine those queries completed at least an order of magnitude quicker (I recently timed it, it was ~4s vs the aforementioned 2 minutes). When things like that jump out at you, make a note and be sure to test on production. To quickly touch on it, there is a difference between performance testing and load testing. In this case, a very specific type of load testing was needed; namely checking out with large quantities in the cart.

To go back to what that professor shot our way every class period: Make sure your system scales. This doesn’t mean overly optimize early on or spend an inordinate amount of time testing every aspect of your system, but make sure to get real numbers in as benchmarks and base levels of speed so that you can check in time to time and be sure your application stays healthy and performant. At a bare minimum, fire up Siege and point it at some endpoints, then run through the most common user flows while New Relic or Librato is hooked up and you’ve got a window up tailing the logs so you can be sure to have a mental model and a few specific numbers of where the majority of requests to your application will go.

Read More...

Core Functionality Of Most Apps

02 January 2017

The more time I spend developing applications, especially as the number of projects increases, the more I find a shared subset of functionality shared among all of them. Thankfully, using base applications as templates and gems I’ve been able to keep master versions of my shared code. They fall into a few categories:

  • Admin Features
  • User Features
  • DevOps
  • Organization

Admin Features

  • Admin Portal
  • Invite Only Sign In
  • Release Notes/Admin Changelog
  • Messaging/notifications to admins

Non-registered User Features

  • Markdown renderable posts (blog, articles etc)
  • Static (or rarely changed), top-level pages
  • Searching

Registered User Features

  • Notifications
  • Messaging
  • Avatar
  • Comments

DevOps

  • Monitoring
  • Deployment
  • Code Health
  • CI/CD

Organization

  • Categories/tagging
  • Tree structures (usually part of the categories)

Search Engines/Integration

  • Dynamic Sitemap
  • RSS Feed
  • Robots.txt
  • Analytics

As I mentioned above, templates and gems are immensely helpful for getting all this up and running, but customizing and configuring all those things for dozens of apps gets tiresome. There have been multiple conversations with myself arguing pros/cons of spinning up my own fuller featured template (which looks more and more like a real CMS every few weeks) vs the existence of many CMSs. Not to mention the lumbering presence of WordPress. Which, as much as I hate working with it, does have almost every imaginable plugin.

You may ask, “What’s the point of this post?”. The point is this: To lay my thoughts out in the open. I’ve found that often, that’s the quickest way to reach a resolution on what should be done with the limited time resources offered us. Most likely in the upcoming months I’ll either discover a nearly perfect CMS solution, or end up creating my own so that future projects can be spun up even quicker, providing a better value to everyone.

Read More...

How to Add Disqus Comments to a Rails 5 Application

19 December 2016

Easy Comments

Even though we’re all capable of building a commenting system from scratch, sometimes public comments for an app are fine and even encouraged (such as enhancing visibility from other sites). I recently added comments to a client’s app and we decided on using Disqus, since it can be dropped in quickly, and all the commented on pages will be public. I’ve written this since the existing Disqus how to’s for Rails which showed up on a google search were outdated; Disqus has since changed their universal js snippet.

The Boilerplate JS

When you want to install Disqus, you register on their site, and they give you a code snippet to insert on every page which you want comments. For this example, we’ve got an Article model, and when viewing each article, want to display comments.

# app/views/articles/show.html.slim
# non relevant erb here 
= render 'disqus'

At which point we’d insert the vanilla Disqus JS into a partial:

<!-- app/views/articles/_disqus.html.erb !-->
<div id="disqus_thread"></div>
<script>
/**
*  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
*  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables
var disqus_config = function () {

};
*/
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = '//nimblefact.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>

From here, all that’s needed is modifying disqus_config as follows:

  this.shortname = "application_name";
  this.page.url = "<%= url_for(host: ENV['APPLICATION_HOST']) %>";
  this.page.identifier = 'article-<%= @article.id %>';
  this.page.title = '<%= @article.title %>';  

At which point, Disqus will load up comments for your page. Easy enough!

Disqus in Rails Application

The one customization I made to the recommended config is this.page.identifier. I scoped that to articles, rather than just inserting the article ID, so that in the future if other models needs comments they can be easily separated from the article comments.

Why Disqus Than Roll Your Own?

As I mentioned, there were no privacy concerns going into this (ie, all pages are public facing anyways), plus this will offload maintenance for both comment functionality and administration. This has enabled us to spend more time on items like addressing page load speeds, Elasticsearch enhancements and functionality which is unique to their business. It saves them money, and allows me to work on much more engaging projects, which is a win for everyone.

Read More...

How to be Productive During the Work Day

10 December 2016

Leonardo DaVinci, A very productive man.

When should you work? How often should breaks be scheduled? How about food, water, workouts? What sort of things alter your mood or mindset throughout the day which can alter your quality and output? What follows are some things to think on as you approach the work week. Focus on these items and be productive over the next week.

Read More...

Cool tricks to do with Ruby, Rails and Pry Part 2: Binding, Awesome Print, Source Edit

10 December 2016

As helpful as George Carlin in Bill and Ted's Excellent Adventure

Part 2 is here with a few enhancements I use in my day to day development, researching and code audits for Ruby and Rails. Check out the first part as well; there’s always more to learn.



Read More...

Previous Page: 3 of 10 Next