cyber101
cyber101

Reputation: 899

Rails - how to cache data for server use, serving multiple users

I have a class method (placed in /app/lib/) which performs some heavy calculations and sub-http requests until a result is received.

The result isn't too dynamic, and requested by multiple users accessing a specific view in the app.

So, I want to schedule a periodic run of the method (using cron and Whenever gem), store the results somewhere in the server using JSON format and, by demand, read the results alone to the view.

How can this be achieved? what would be the correct way of doing that?

What I currently have:

def heavyMethod
   response = {}
   # some calculations, eventually building the response
   File.open(File.expand_path('../../../tmp/cache/tests_queue.json', __FILE__), "w") do |f|
      f.write(response.to_json)
   end
end

and also a corresponding method to read this file.

I searched but couldn't find an example of achieving this using Rails cache convention (and not some private code that I wrote), on data which isn't related with ActiveRecord.

Thanks!

Upvotes: 1

Views: 987

Answers (1)

Karthik T
Karthik T

Reputation: 31962

Your solution should work fine, but using Rails.cache should be cleaner and a bit faster. Rails guides provides enough information about Rails.cache and how to get it to work with memcached, let me summarize how I would use it in your case

Heavy method

def heavyMethod
   response = {}
   # some calculations, eventually building the response
   Rails.cache.write("heavy_method_response", response)
end

Request

response = Rails.cache.fetch("heavy_method_response")

The only problem here is that when ur server starts for the first time, the cache will be empty. Also if/when memcache restarts.

One advantage is that somewhere on the flow, the data u pass in is marshalled into storage, and then unmartialled on the way out. Meaning u can pass in complex datastructures, and dont need to serialize to json manually.

Edit: memcached will clear your item if it runs out of memory. Will be very rare since its using a LRU (i think) algoritm to expire things, and I presume you will use this often. To prevent this,

  1. set expires_in larger than your cron period,
  2. change your fetch code to call the heavy_method if ur fetch fails (like Rails.cache.fetch("heavy_method_response") {heavy_method}, and change heavy_method to just return the object.
  3. Use something like redis which will not delete items.

Upvotes: 2

Related Questions