skip to Main Content

I have two Rails Apps that need to share some state. Each App needs to run background jobs during their execution lifetimes. I added Heroku Redis to each App, and Sidekiq. So when I run background jobs, everything is great.

I do not have shared state until I point one App’s REDIS_URL at the other Apps REDIS_URL and then both Apps are using the same shared Redis instance, I assume, and hence I have some shared state.

Now both Sidekiq instances share the same Redis, and one App is seeing the other Apps jobs and puking, because it has no idea about the other Apps jobs.

What is a clearer way of sharing state and keeping the jobs separate like they should be? I guess I need to just buy a cache I can use as shared state separate from the jobs?

Heroku App 1. Owns Redis Instance. Has Sidekiq. Runs Job AaaBbbJob
Heroku App 2. Points at Redis Instance from App1. Has Sidekiq

I notice the logs for App 2 show job AaaBbbJob tried running and failed as AaaBbbJob was not found.

In the logs of App 1, Job AaaBbbJob ran fine…

So my confusion lies in trying to assure myself that this is all OK. When App 1 through a job via Sidekiq into Redis, for whatever reason, App 2 saw that job in Redis too, and tried to run it.

So my question is, since throwing Jobs into Redis is now shared between two Apps, they both try and run ANY jobs they see?

2

Answers


  1. You have two problems here :

    • 2 different apps use Sidekiq and share the same Redis instance
    • need to exchange data between two apps

    For the first question, your 2 apps may have different Sidekiq Jobs but because of the same Redis instance, each of the Background app (which runs respective apps slug) pick all Sidekiq Jobs and only understand the jobs that they know about.

    You can’t really help as Sidekiq is done like this. It is a feature that allows to run multiple dynos with Sidekiq for the same app.

    What you can do to separate the two types of Sidekiq jobs is to assign a redis Database to each app : What's the Point of Multiple Redis Databases?

    Redis can segregate data into 16 different databases.

    For example my Redis config in one of my app is :

    config/redis.yml

    development:
      url: redis://localhost:6379/
      db: 2  
    
    production:
      url: <%= ENV["REDIS_URL"] %>
      db: 2
    
    test: 
      url: redis://localhost:6379/
      db: 2 
    

    In another app I am using the database number 1. Then there is no collision.

    The matching Sidekiq initializer looks like this then :

    conf = Rails.application.config_for(:redis)
    confid = conf.merge({id: "Sidekiq-server-PID-#{::Process.pid}"})
    confservid = conf.merge({id: "Sidekiq-server"})
    
    if Rails.env.production?
    
      Sidekiq.configure_client do |config|    
        config.redis = conf    
      end
    
      Sidekiq.configure_server do |config|    
        config.redis = conf    
      end
    
    end
    
    
    if Rails.env.development?
      Sidekiq.configure_client do |config|         
        config.redis = confid    
      end
    
      Sidekiq.configure_server do |config|    
        config.redis = confservid        
      end
    
    end
    

    As you can see I am naming all redis clients (in development) on top of what I have explained. It is very useful to understand Redis clients consumption.

    Regarding your second question: sharing "app state" I think it is about sharing global values such as constants or class variables.

    It is probably possible to share this data through Redis but this is definitely ugly. You turn 2 apps a single monolith.
    Even if you manage to do it properly, you have to rewrite everything when you want each app to have its own Redis instance.

    The only way to do this is through a controller behaving as an API that would answer requests and deliver data to the other app.

    Login or Signup to reply.
  2. Each app will need a Redis connection pool for the other Redis instance. Then App A can use those connections to send data or jobs to App B or push jobs to its sidekiq. Using multiple Redises is known as sharding.

    https://github.com/mperham/sidekiq/wiki/Sharding

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search