- vừa được xem lúc

Dùng Sidekiq vào tính năng xếp hạng 1 dãy các dữ liệu

0 0 20

Người đăng: Hoàng Đức Quân

Theo Viblo Asia

Dạo gần đây mình có khởi động lại project cá nhân để luyện tập tay nghề(Hàng dùng view mặc định của Ruby, không dùng framework JS tử tế cho frontend và dùng Bootstrap 5.3 làm giao diện thôi. Cũng tối cổ so với trend TailwindCSS với chỗ React và VueJS). Ý tưởng thì là 1 website chứa lyrics, tua nhạc và có metronome chạy theo đúng tempo bài hát. Cái mà mình lần trước có deploy với AWS AppRunner rồi nhưng chưa đưa video được.

Vấn đề

Trong quá trình làm thì mình có nảy ra thêm việc tích hợp 1 số tính năng bảng xếp hạng âm nhạc, thông tin nghệ sĩ,.... Nhưng với quá trình xếp hạng ấy cũng nảy ra vấn đề làm sao để đánh giá nghệ sĩ từ bài hát và album của họ?

Và một trong những giải pháp ở đây là đánh giá dựa trên lượt view bài hát và lượt view album. Các nghệ sĩ sẽ được đánh giá dựa theo tổng lượt view của tất cả các bài hát và tất cả các album.(Đây là giải pháp của mình. Thực tế có thể sẽ có khác)

Vì vậy trước tiên mình có db như này và đã triển khai ổn thoả:

image.png

OK, đã có lượt view của album và lượt view của bài hát. 2 dữ liệu này sẽ được refresh mỗi khi có 1 người dùng vào trang info của 1 album hay 1 bài hát nào đó.

Tuy nhiên, nếu cứ mỗi lượt view được add vào như vậy, dẫn đến albums_pointssongs_points sẽ thay đổi realtime, dẫn đến mọi người khác nhau có thể sẽ nhìn bản xếp hạng ở những vị trí khác nhau(rất phù hợp với tính năng trending nhưng không phù hợp lắm với xếp hạng). Mình muốn bảng xếp hạng theo lượt view được cố định trong 1 tuần rồi có bảng xếp hạng mới.

Và để giải quyết thì mình quyết định chạy scheduled job để cập nhật hàng tuần. Đó là lý do động vào Sidekiq

Code

Gemfile

Trước tiên, ở Gemfile mình thêm sidekiq như sau

# Gemfile
# ...
# Use Sidekiq
gem 'sidekiq'
gem 'sidekiq-scheduler'

Sau đó chạy bundle update

docker-compose

 redis: image: redis ports: - "6379:6379" app: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails assets:precompile && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/rails-lyrics-site - bundle:/usr/local/bundle - tmp-data:/rails-lyrics-site/tmp - public-data:/rails-lyrics-site/public ports: - "3000:3000" depends_on: - db - redis sidekiq: build: . command: bundle exec sidekiq volumes: - .:/rails-lyrics-site depends_on: - db - redis

sidekiq muốn hoạt động được phải phụ thuộc vào redis, và cũng cần được tách ra như 1 component riêng chạy song song song với phía container web nên ta thêm định nghĩa container:

 redis: image: redis ports: - "6379:6379"

 sidekiq: build: . command: bundle exec sidekiq volumes: - .:/rails-lyrics-site depends_on: - db - redis

Cuối cùng thêm container phụ thuộc ở app.

Setup phía config

Ta cần setup:

  • config/application.rb:
 config.active_job.queue_adapter = :sidekiq
  • Tạo mới config/initializers/sidekiq.rb:
redis_config= { url: 'redis://redis:6379/0' } Sidekiq.configure_server do |config| config.redis = redis_config
end Sidekiq.configure_client do |config| config.redis = redis_config
end
  • Thêm Sidekiq view ở config/routes.rb
# frozen_string_literal: true
require 'sidekiq/web'
require 'sidekiq-scheduler/web' Rails.application.routes.draw do # .... mount Sidekiq::Web, at: '/sidekiq' match '*unmatched', to: 'application#not_found', via: :all # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
  • Tạo mới config/sidekiq.yml:
:scheduler: :schedule: update_artist_pop_points: cron: '0 30 6 * * 1' class: ExampleJob

Bước cuối là start server lên kiểm tra localhost:3000/sidekiq. Khi hiện màn hình giống như này tức là các bạn thành công.

image.png

Tạo 1 job và chạy thử

Để tạo 1 Job trong Rails, chúng ta có command rails g job. Ví dụ, để tạo 1 Job có trên là Blo.....omJob, ta chạy rails g job bloom Ở tình huống này mình sẽ chạy:

rails g job UpdateArtistPopPointsJob

app/jobs/update_artist_pop_points_job.rb, mình thêm code:

# frozen_string_literal: true class UpdateArtistPopPointsJob < ApplicationJob queue_as :default def perform(*_args) # Do something later Artist.find_each do |artist| artist.songs_points = 0 artist.albums_points = 0 artist.albums.each do |album| artist.albums_points += album.views_count end artist.songs.each do |song| artist.songs_points += song.views_count end artist.save! end end
end

Chỉnh lại config/sidekiq.yml:

 class: UpdateArtistPopPointsJob

Các bạn có thể thấy là giờ Job của mình đã được lên ở trong Sidekiq và kích hoạt trong 6 ngày nữa. Mình có thể lựa chọn kích hoạt luôn.

Bonus: Authentication cho sidekiq

Rõ ràng trang kia thiên hướng về phía admin. Thế nên để chỉ admin xem được trang này, mình sẽ chỉnh ở routes:

 authenticate :user do mount Sidekiq::Web, at: '/sidekiq' end

Kết

Bài mình viết tới đây là hết

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 393

- vừa được xem lúc

Phần 1: Giới thiệu về Kubernetes

Kubernetes là gì. Trang chủ: https://kubernetes.io/. Ai cần Kubernetes.

0 0 96

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 1- Lịch sử)

1. Vì sao nên sử dụng. . .

0 0 102

- vừa được xem lúc

Docker - những kiến thức cơ bản phần 1

Giới thiệu. Nếu bạn đang làm ở một công ty công nghệ thông tin, chắc rằng bạn đã được nghe nói về Docker.

0 0 77

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 2 - Dockerfile)

1. Mở đầu.

0 0 65

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 3: Docker-compose)

1. Mở đầu. . .

0 0 119