At Salsify we run most of our Ruby on Rails based infrastructure in Heroku. We recently switched our Puma web workers over from Heroku 2X dynos to more powerful Heroku PX dynos and saw dramatic performance improvements: a 51% reduction in mean response time and a 59% reduction in 99th percentile response time. Based on this we did some experiments running our more memory/CPU intensive Delayed Jobs on PX dynos and saw a similarly encouraging 43% reduction in mean job execution time and 66% reduction in 99th percentile job execution time. This was great for a proof of concept, but only one of the eight cores on the PX dyno was being used. In order to take this to production in a cost-effective manner, we had to figure out how to utilize all of the cores on the dyno.
At Salsify, we manage the flow of product information between manufacturers, and distributors through to large retail outlets such as Walmart and Google Shopping. Our flexible schema allows users to describe their products however they see fit. We store product attributes in a single table, but each product attribute has a potentially different data type and associated application-specific logic.
When debugging software, particularly if it's code you didn't write and aren't familiar with, one of the hardest parts can be just determining where to start. Without the right context, you can end up chasing red herrings all over before finally tracking down the underlying problem. Well-placed log messages can help provide that context, saving that time and frustration. In this post, we'll look at adapting a logging technique employed by many Node tools on the command line for use in an Ember.js app in the browser.
By Randy Burkes on Oct 28, 2014 2:18:28 PM
Salsify is a multi-tenant SaaS product information exchange platform hosted in Heroku. We utilize delayed job extensively for long running tasks like import/export/search indexing/etc. One of the features we've grown to love about delayed job is its extensibility via plugins (see our other posts). Recently, an increasing number of job workers have been exceeding their dyno memory quota**, and consequently suffering serious performance degradation. While we are always working to improve our code performance, we thought it would be nice to have a mechanism for euthanizing workers that are unrecoverably exhausted. Enter the DelayedJob::YouthInAsiaPlugin.
Over the past few months at Salsify we've spent some time exploring Ember.js and incorporating it into parts of our front-end. There's a lot to say on the topic, but today we'll just be taking a look at one of our first forays outside of the land of Ember's baked-in pieces: automatically generating breadcrumbs based on a user's application state.
Most Rails developers quickly learn that minimizing the number of database queries by properly specifying eager loads is critical for good application performance. Unfortunately specifying eager loads is error prone and can cause encapsulation problems. In this post we'll explore having Rails automatically handle eager loads.
I wanted to share a bit of information that we found interesting when writing active record migrations on tables leveraging STI (Single Table Inheritance). We came across a not so obvious gotcha with STI models re-defined in migration classes and wanted to explore our thought process while solving the subsequent problems.
By Joel Turkel on Dec 12, 2013 4:45:00 AM
Previously we blogged about eager loading calculations with database views in Rails to avoid running lots of database queries. The approach we described really only works if your SQL is fairly static and you don't mind creating database views for each of your calculations. In this post we'll explore an alternative approach that avoids these issues by not using database views. First let's quickly recap the problem...
By Joel Turkel on Oct 30, 2013 6:15:00 AM
Update: The plugin discussed in this post has been packaged into the delayed_job_heartbeat_plugin gem.
Previously we've blogged about how to write Delayed Job plugins and how to aggregate jobs into job groups. In this post we'll explore how to proactively detect failed Delayed Job workers so their jobs can be retried in a timely manner. This is useful if a worker crashes, is automatically restarted by your platform provider, or is shutdown by auto-scaling infrastructure.