使用Docker安装Rails、Sidekiq和Redis,在指定的时间执行作业

首先

在这篇文章中,我们将介绍如何使用Docker设置Rails、Sidekiq和Redis,并在指定的时间执行作业。本次例子中,我们将以向用户发送提醒邮件的功能为例。

Sidekiq 是什么?

Sidekiq是一个用于Ruby的背景作业处理库,用于执行异步处理。它用Redis作为后端来管理创建的作业。

非同步處理是指不需要等待前一項處理完成的行動。

程序同时执行多个任务。通过在后台执行繁重或耗时的操作,可以提高性能。
常见的做法是异步处理时间较长的任务,比如发送邮件或批量处理数据。

Docker和Docker Compose的配置

首先,使用Docker和Docker Compose来设置Rails、MySQL、Redis和Sidekiq的各个服务。在项目的根目录下创建以下Dockerfile和docker-compose.yml文件。

FROM ruby:3.1
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
apt-get install -y nodejs
ENV TZ=UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN mkdir /VehicleMinders
WORKDIR /VehicleMinders
COPY Gemfile /VehicleMinders/Gemfile
COPY Gemfile.lock /VehicleMinders/Gemfile.lock
RUN bundle install
COPY . /VehicleMinders

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]
version: '3'
services:
  db:
    platform: linux/amd64
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql-data:/var/lib/mysql
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
      - redis
    stdin_open: true
    tty: true
  sidekiq:
    build: .
    command: bundle exec sidekiq
    volumes:
      - .:/app
    depends_on:
      - db
      - redis
  redis:
    image: redis
volumes:
  mysql-data:
    driver: local

Sidekiq的配置

配置Sidekiq。在Gemfile中添加gem ‘sidekiq’,然后运行bundle install。

gem 'sidekiq'

为了使用Sidekiq的仪表板功能,在routes.rb中添加以下代码。
通过访问http://localhost:3000/sidekiq,可以查看正在运行的作业和等待执行的作业。

Rails.application.routes.draw do
  require 'sidekiq/web'
  mount Sidekiq::Web => '/sidekiq'
end

创建Sidekiq的配置文件sidekiq.rb。在该文件中,对Sidekiq连接Redis服务器的配置进行设置。

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

创建电子邮件发送功能

创建一个用于发送电子邮件的UserMailer。

class UserMailer < ApplicationMailer
  def reminder_email(user)
    @user = notification.user
    mail(to: @user.email, subject: 'Your reminder')
  end
end

创建电子邮件发送任务

创建一个在指定时间发送电子邮件的作业。将其创建在 app/workers 目录中。
作业是一个执行特定任务的类,包含 Sidekiq::Worker 模块,并定义 perform 方法。perform 方法在作业被执行时会被调用。

class ReminderMailerWorker
  include Sidekiq::Worker

  def perform(notification_id)
    notification = Notification.find(notification_id)
    UserMailer.reminder_email(notification).deliver_now
  end
end

提醒事项的调度

安排提醒事项的日程安排。这次,我们向 Notification 模型添加了 after_create 和 after_update 的回调函数,并安排了发送提醒邮件的日程安排。
要将作业添加到队列中,可以使用 perform_async 方法。该方法会将作业保存到 Redis 中,然后在后台执行。
在下面的示例中,我们使用 perform_at 方法来指定执行 perform 方法的时间作为第一个参数。

class Notification < ApplicationRecord
  belongs_to :user
  after_save :schedule_reminder_mailer, if: -> { self.datetime.present? }

  private
  def schedule_reminder_mailer
    ReminderMailerWorker.perform_at(self.datetime, self.id)
  end
end

总结

这次介绍了使用Sidekiq在指定的时间执行作业的方法。还有一个名为sidekiq-cron的宝石,它可以用来管理需要定期执行的作业。

参考资料・网址

Sidekiq的使用方式
官方GitHub

bannerAds