Blog #8

Redis, Sidekiq and Rails Catching

# Redis

Redis - Wikipedia

I want to make a brief introduction so that you can understand easily. 
Redis is simply a database, for me, it is the place I use to store less important things like cache. 
In addition, it combines with Sidekiq very powerfully, it helps Sidekiq to save queues, processes, cron jobs… 
This blog of mine will guide you to put them together.

# Sidekiq

Sidekiq

Sidekiq is used to handle background jobs (asynchronous jobs).
Sidekiq has the ability to handle multiple jobs concurrently, helping to get the job done quickly.

# How does Sidekiq work?

Sidekiq works with 2 main threads. Those are sidekiq_client and sidekiq_server

# Sidekiq Client

  1. Responsible for pushing jobs to queues.

# Sidekiq Server

  1. Responsible for getting jobs from queues.

# Config

Add to Gemfile

# Sidekiq and Redis
gem 'sidekiq', '~> 5'
gem 'sidekiq-cron'
# Use Redis adapter to run Action Cable in production
gem 'redis', '~> 4.5.1'
$ bundle install

Open the file config/application.rb and add this line:

config.active_job.queue_adapter = :sidekiq

Create new file config/initializers/sidekiq.rb

Sidekiq.configure_server do |config|
  config.redis = { url: "redis://127.0.0.1:6379/#{ENV['REDIS_PORT']}" }
  config.on(:startup) do
    schedule_file = 'config/schedule.yml'

    Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) if File.exist?(schedule_file)
  end
end

Sidekiq.configure_client do |config|
  config.redis = { url: "redis://127.0.0.1:6379/#{ENV['REDIS_PORT']}" }
end

Open the file routes.rb and add this line:

require 'sidekiq/web'
require 'sidekiq/cron/web'

If you want to authenticate for administrator when open sidekiq page, puts this line in your routes.rb

authenticate :administrator do
  mount Sidekiq::Web => '/sidekiq'
end

Config sidekiq setting in config/sidekiq.yml:

---
:verbose: false
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:concurrency: 5
staging:
  :concurrency: 10
production:
  :concurrency: 20
:queues:
  - critical
  - default
  - low

After start Rails server, start Sidekiq server by command line:

$ bundle exec sidekiq -e development -C config/sidekiq.yml

# Use

Enqueue the job:

perform_now: enqueue the job currently.

VocabularyJob.perform_now('hello')

perform_later: enqueue the job after a period of time.

VocabularyJob.set(wait_until: 3.hours).perform_later('hello')
# Push job to queue immediately
# Take up the queue and soak for 3 hours, it's a waste of space!

VocabularyJob.set(wait: 3.hours).perform_later('hello')
# Push job to schedule
# After 3 hours push the job to queues => don't waste space

# Caching

def caching_limit
  Rails.cache.fetch('chat_gpt_call_times', expires_in: 1.minute) do
    "1/#{Time.zone.now.to_i}"
  end
end

If you call the caching_limit method for the first time it will save it to Redis and count down time.

And the next time you call caching_limit in time during its lifetime, it will get the initialization value to use, and no need to re-run the code inside.

You can read the cache values through Redis or via Rails

 Rails.cache.read('chat_gpt_call_times')

And you can also update its value:

Rails.cache.write('chat_gpt_call_times', "1/#{Time.zone.now.to_i}", expires_in: 1.minute)