ArtPulse
ArtPulse

Reputation: 365

Refresh data with API every X minutes

Ruby on Rails 4.1.4

I made an interface to a Twitch gem, to fetch information of the current stream, mainly whether it is online or not, but also stuff like the current title and game being played.

Since the website has a lot of traffic, I can't make a request every time a user walks in, so instead I need to cache this information.

Cached information is stored as a class variable @@stream_data inside class: Twitcher.

I've made a rake task to update this using cronjobs, calling Twitcher.refresh_stream, but naturally that is not running within my active process (to which every visitor is connecting to) but instead a separate process. So the @@stream_data on the actual app is always empty.

Is there a way to run code, within my currently running rails app, every X minutes? Or a better approach, for that matter.

Thank you for your time!

Upvotes: 0

Views: 1477

Answers (3)

Frederick Cheung
Frederick Cheung

Reputation: 84114

This sounds like a good call for caching

Rails.cache.fetch("stream_data", expires_in: 5.minutes) do
  fetch_new_data
end

If the data is in the cache and is not old then it will be returned without executing the block, if not the block is used to populate the cache.

The default cache store just keeps things in memory so doesn't fix your problem: you'll need to pick a cache store that is shared across your processes. Both redis and memcached (via the dalli gem) are popular choices.

Upvotes: 1

matthewdu
matthewdu

Reputation: 43

I actually had a similar problem with using google analytics. Google analytics requires that you have an API key for each request. However the api key would expire every hour. If you requested a new api key for every google analytics request, it'd be very slow per request.

So what I did was make another class variable @@expires_at. Now in every method that made a request to google analytics, I would check @@expires_at.past?. If it was true, then I would refresh the api key and set @@expires_at = 45.minutes.from_now.

You can do something like this.

def method_that_needs_stream_data
  renew_data if @@expires_at.past?
  # use @@stream_data
end

def renew_data
  # renew @@stream_data here
  @@expires_at = 5.minutes.from_now
end

Tell me how it goes.

Upvotes: 0

Wes
Wes

Reputation: 487

Check out Whenever (basically a ruby interface to cron) to invoke something on a regular schedule.

Upvotes: 0

Related Questions