how to use memcache to speed-up rails/heroku - ruby-on-rails

Heroku supports memcache natively as an addon. my problem is, being a rails newbie still, I have no clue how to use memcache in order to speed-up my most time-consuming request (I know which they are by looking a the newrelic analysis). should we use a gem like 'cache-money' on-top of memcache? does anyone use act_as_cached anymore?
I know this is a pretty trivial questions. Yet after searching the web for hours, I could not find a decent tutorial. Any help/link appreciated!

You can watch Caching in Rails 2.1 and then read the memcached documentation (I suppose you have already read it) in Heroku.
Also, Touch and Cache is quite interesting technique to avoid writing Sweepers in order to delete cached content when you need to refresh the cached data. Using touch will auto expire cached data with almost no need to write new code.
Please note that today, the Heroku memcached integration assumes you are using Rails >= 2.3.3
The main idea is that you add the result(s) of your time consuming method to Rails.cache (which is the interface through which you access your caching mechanism). When you fetch that result(s) the caching mechanism searches to see if it can find it or if it hasn't expired.
If it finds it, it returns it very fast because it takes it from the cache.
If it doesn't find it or it has expired (you set this when you call fetch), it runs the actual slow method to add it or refresh it in cache.
Finally, it is very useful to read the Rails documentation apart from whether you are using memcached or the built in Rails caching: Caching with Rails: An overview. Among other things it talks about:
Page caching
Action caching
Fragment caching
Sweepers
SQL caching
and more ...

You can cache on memcache the action_cache or you can access to memcache with Rails.cache

Related

activestorage without time limited urls

I'm not totally up to date with the latest developments in ActiveStorage. I'm using Rails 5.2.x and have a deep problem. The default URL generated for assets is a time limited call to
{host}/rails/active_storage/blobs/{long-obfuscated-stuff-here}/{the-actual-file}
This method obviously had a clear use case in BaseCamp, but if you're using a CDN or Nginx/Apache to serve assets directly from disk, it's as useful as a chocolate teapot because every request has to go through rails/active_storage/blobs and as it's a time limited unique url it can't be cached.
I see long threads on this problem trying to get core devs to accept PRs to fix this problem (e.g. github issue 34477 )
And the problem might be fixed in the latest Rails 6. But I'm on Rails 5.2 and won't be upgrading in the near future.
So I need to know how to get the raw url for the base file so I can serve it directly from Nginx/Apache without going through the Rails stack.
Any suggestions?
I would wait for a good solution to actually land in Rails, but you could always:
config.active_storage.service_urls_expire_in = 99.years
Again, I'm not sure this is really the right thing to do but if you absolutely have to have permanent URLs it would work.

Rails 3.2 where is fragment cached data getting stored?

I have created rails application and I have used fragment caching concept. Where is cached data getting stored and how can I access those data? How do I know whether caching is working or not?
Take a look into fragment caching docs for references (you are particularly interested in ActionController::Caching::Fragments).
You may want to check
ActiveSupport::Cache.expand_cache_key(key, namespace)
to check specific key for whether it is being cached.
To check the cache storage you can check the
config.action_controller.page_cache_directory
P.S. It's high time to upgrade your Rails version ;)
Eventually I got the solution.
Cached data will stored based on cache_store used in environment configuration.
Ex)
Some available cache_stores are memory_store, file_store,.. etc
I have configured file_store in development environment then the data will be stored in rails_root/tmp/cache directory

How can I cache external API requests to the SQL database using Rails cache API?

I'm just wondering how I can cache slow requests to external APIs in the database, as I do not want to maintain a memcache service, but I do want a distributed system that will work across multiple dynos and workers on heroku.
I can do it by building my own cache table, but I'm wondering if there's an easier way, especially one that works with the existing caching syntax.
Thanks!
You can cache just about anything in Rails via a call to Rails.cache.fetch. You pass in a key for the cache to look up, and if there's a value in the cache (a "cache hit") then it will get used instead of your slow code.
Let's say we've got an API that takes two airport codes and a date, and returns the best price it can find. This can be a slow lookup, so it's a good candidate for caching:
def find_best_price(start_airport, end_airport, date)
Rails.cache.fetch(cache_key_for(start_airport, end_airport, date)) do
AirportPriceAPI.find_best_price(start_airport, end_airport, date)
end
end
# Different routes & dates will have different prices, so we
# need to have different cache keys for them.
def cache_key_for(start_airport, end_airport, date)
"best_price:#{start_airport}:#{end_airport}:#{date}"
end
You can configure the data store for your cache in config/application.rb by setting config.cache_store. Rails has several kinds built in, but not all are suitable for Heroku. You can't use the FileStore because dynos don't have persistent storage and it's not shared between dynos. MemoryStore isn't shared across dynos and will be wiped out if your dyno restarts.
Your best bet for Heroku is the MemCacheStore. It's supported out-of-the-box in Rails, and Heroku will give you 30Mb of memcache space for free. It's fast and perfect for use between multiple dynos.
But, if you did want to cache values in a database, you can provide your app with a custom cache class. All you have to do is extend ActiveSupport::Cache::Store and be sure to implement read, write, exist?, delete, and fetch. And someone's already packaged a DB-backed cache store as a gem, so you don't even have to implement the low-level details yourself. :)

Cache strategy in a rails application using membase, how do I make sure I don't delete everything?

I have a rails application.
I am using membase/memcache to cache DB objects and HTML partials.
I cache db objects with the create operation and of course find operations etc...
now, when I do User.find(1).
this is cached as an object in memcache.
I have a pretty good strategy with caching these along side with the HTML content.
now, when I deploy, one of the thing my Capistrano script is doing is to clear the cache (because of the html partials that change) but there's really no reason to invalidate the cache of the db objects.
How can I only delete part of my cache?
Can this be done?
my cache keys look like this
DB: user_find_by_id_10000
HTML: user_profile_home_1000
Would appreciate you help
Thanks.
It might also be a good idea to user separate buckets for your DB cache and your HTML cache...then you can use the 'flush_all' command to clear out a whole bucket without affecting the other one.
Also, looking forward to Couchbase Server 2.0 which will be in a developer preview at the end of this week, you'll be able to create indexes and views to return just the data that you're looking for, you can then feed that through a little process to delete all the items that match a certain criteria.
Perry Krug
Solutions Architect, Couchbase Inc.
It's fairly simple to delete a cached item based on its key:
Rails.cache.delete('user_profile_home_1000')
In the code above I'm assuming you've set Rails' cache to use Memcached.

Rails Memcached Caching

I am using memcached in production on a high traffic website and have only just switched to using Rails.
I am using Rails 2.3.2.
My question is: Is caching of of queries done automatically with this version of Rails? Or do I have to explicitly cache these queries?
I have seen conflicting documentation on this issue, and I am afraid of having to restart memcached to see exactly what is happening.
The documentation on this w.r.t rails seems patchy. I would appreciate if you could also point out the best place to read up on this.
Thanks!
Vikram
If you haven't explicitly set out and configured certain actions to be cached they won't be, so I would guess right now that you aren't actually using your memcached like you think you are.
As a starting point I'd recommend reading this article on the different methods of setting up caching within Rails.
I've also found this presentation to be useful as well as this excellent screencast.
If you're looking for help, it would be useful to know more of what you're trying to do: how write heavy is the application? How may pages / views / users are you trying to serve?

Resources