Is Caching the Right Way to Speed Up Your Ruby on Rails App? We’ve all been there. You’re clicking around your Rails application, and it just isn’t as snappy as it used to be. You start searching for a quick-fix and find a lot of talk about caching. Take your existing app, bolt on some caching, and voila, a performance boost with minimal code changes. However, it’s not this simple. Like most quick fixes, caching can have long-term costs.
I’ve spent a few months now using the interactor gem, both in my day job and also quite extensively in GitArborist’s code. My first time hearing about “interactors” was from a talk by Robert Martin on clean architecture, essentially saying that an “interactor” object should encapsulate a single “use case” or user story, basically the business logic. Therefore, if you look at a list of interactors in the system you can quickly determine what operations that system carries out (in theory).
In an earlier post, I wrote about how the code I’m most proud of is terrible code. This is because although the code is terrible when I come back to it to change something after 6 or 12 months I can quickly find where the change needs to be made.
When describing this to someone they asked me why it is easy for me to navigate the codebase. Obviously, this code came out of my head so I have an unfair advantage here, I can’t pretend this is not a factor.
A common question in developer job interviews is to ask about code that the interviewee is proud of. The assumption here, of course, is that the code you’re most proud of is good code, but is it?
The code I’m most proud of was a full re-write of a PHP (i.e. LAMP stack) application for attendance marking. The original app was a collection of standalone PHP files with PHP, HTML, and SQL all mixed with minimal structure.
ActiveJob is Rails’ way of handling background jobs, providing a common interface around various queuing backends that do the actual processing (Sidekiq, Resque, etc). ActiveJob’s interface is pretty simple, you call #perform_later on the job, that job gets added to the queue, and at some point, a worker process will pick it up and execute it.
You can also set various options via the set method, for example:
ThingJob.set(wait: 1.day).perform_later will cause the job to be executed one day from now.
Performance Woes I’ve been running GitArborist for a couple of months now, gradually adding features. Like any good production app, I have some logging and metrics set up to monitor and troubleshoot issues.
Over these last few months, I’ve seen recurring performance issues, with response times in double-digit seconds in some cases. I made various fixes like you’d expect: adding database indexes, returning early where possible, etc. These were improvements to be sure, but I never fully removed these occasional long response times, though I could not reproduce it myself.