Henley Chiu Henley Chiu - 3 months ago 12
Ruby Question

How to update a global Rails variable in some sort of job?

I have a global variable in one of my Rails initializer config/initializers/globals.rb. This variable is simply a list, set to the members of a Redis set.

$listOfBannedDomains = $redis.smembers("banned_domains")


The Redis set gets updated once in awhile. How can I update $listOfBannedDomains with what's in the Redis set once every X hours without restarting my Rails app?

Note that I do not want to read from the Redis set in real-time.

Answer

You can use EventMachine for this and utilize it's perioidic timer to do that asynchronously in an evented loop.

Create a new rails initializer - config/initializers/redis_periodic.rb

$listOfBannedDomains = $redis.smembers("banned_domains")

Thread.new { EM.run } unless EM.reactor_running? # Run the EventMachine reactor if it's not running already in a new thread.
Signal.trap("INT")  { EM.stop }
Signal.trap("TERM") { EM.stop }

# Add a periodic timer:
time_interval = 5 #seconds
EM.add_perioidic_timer(time_interval) do
  # Update the constant by re-reading from redis
  $listOfBannedDomains = $redis.smembers("banned_domains")
end

Note: This won't block your main Rails thread from requests and will allow you do that operation asynchronously, per rails instance. You can add extra conditions in initializer to exclude this from happening in Rake(if required).