Kaynaklar:
Rails Guides
Not: Anlatımda ruby-2.6.3
, rails-6.0.0.rc2
kullanılmıştır.
Arkaplan Görevi Nedir?
Rails’da arka plan görevlerini yönetmek için kullanılan Active Job’u açıklamaya başlamadan önce ilk olarak arkaplan görevi kavramının ne olduğuna açıklık getirmek gerekiyor.
Arkaplan görevleri bir işlemin durmasına rol açmadan, eş bir çizgide yürüyerek rol almasıdır. E-posta yollanması buna çok güzel bir örnektir. Örneğin kullanıcı sistemimize kayıt olmak için kayıt ol formunu doldurduğunda onaylama epostası yollanıyor olsun. Kullanıcı bu tuşa bastığında eposta yollama işlemini direkt olarak işleme alırsak, e-posta yollanasıya kadar kullanıcı yükleme ekranında bekler. Fakat eğer arka plan görevi olarak çalışmasını sağlar ise işlem bir kuyruğa alınır ve sayfa direkt yüklenir.
Nerelerde Arkaplan Görevlerine İhtiyaç Olabilir?
Örneğin bir kullanıcı alışveriş sitesinden bir şey satın aldığında arka planda bir fatura oluşturup e-posta olarak yollamak gerekir. Bu fatura oluşturma ve e-posta yollama aşamalarında arka plan görevi kullanmak mantıklı olacaktır.
Ya da şunu hayal edin haftalık bülten sitemiz var. Kullanıcı e-postasını sisteme girdiğinde haftalık olarak bilgilendirme e-postası almak istiyor, bu durumda da arka plan görevleri kullanmak mantıklı olacaktır.
Active Job nedir?
Active Job, zamanlanmış olarak çalışacak görevleri tanımlayan, bu görevlerin kuyruk servislerine (çoğunlukla III. parti) aktarılmasından sorumlu bir framework yani uygulama çatısıdır.
Active Job’un ana amacı; Kuyruk(queue) amacıyla kullandığımız III. parti servisi değişse dahi daha önceden yazmış olduğumuz görevlerin yani job’ların baştan yazımının önüne geçmektir.
Active Job sayesinde görevlerimizi yazabilir ve istediğimiz kuyruk servisi kullanabilir, değiştirebiliriz.
Kuyruk Servisleri
Rails’de varsayılan olarak kuyruk mekanizması RAM üzerinde tutulacak şekildedir. Herhangi bir elektrik kesintisinde ya da RAM’de oluşacak bir sorunda kuyruktaki tüm görevler yok olacaktır.
Bu durumda III. parti bir kuyruk servisi kullanmak mantıklı olabilir.
Bu servislere Sidekiq
, Resque
, Delayed Job
vs. örnek verilebilir.
Servislerin güncel listesine buradan QueueAdapters bakılabilir.
Kuyruk servisini ayarlamak oldukça basit. Config dosyasında belirtmemiz yeterli.
config.active_job.queue_adapter = :sidekiq
Ya da görev bazlı olarak seçeceğimiz servisi değiştirebiliriz. Yani config dosyasında varsayılan olarak ayarlanan servisin üzerine yazmış oluruz. Örneğin haftalık bülten görevi için “sidekiq” kullanırken, ödeme hatırlatıcı e-postaların atılması için “resque” kullanabiliriz.
class NewsletterJob < ApplicationJob
self.queue_adapter = :sidekiq
end
class FeeJob < ApplicationJob
self.queue_adapter = :resque
end
Ben, bu örnekte sidekiq kullanmayı tercih ettim.
Bunun için Gemfile’e sidekiq’i eklemeli ve routes dosyasını da aşağıdaki gibi ayarlamalısınız. Ayrıca sidekiq çalışmak için redis sunucusuna ihtiyaç duyuyor.
Gemfile
gem 'sidekiq', '~> 5.2', '>= 5.2.7'
Routes
require 'sidekiq/web'
require 'sidekiq/cron/web'
Rails.application.routes.draw do
mount Sidekiq::Web, at: '/sidekiq'
end
Kullanıcı Kayıt Olduğunda Arkaplanda E-posta Atılması
Uygulamızda kullanıcılar kayıt olduğunda arka planda e-posta yollamak istiyoruz.
Kullanıcıyı yaratalım.
rails generate scaffold User name:string email:string
E-posta yollayabilmek için mailer ekleyelim
rails generate mailer UserMailer
Bu mailer’e welcome diye bir method ekleyelim
class UserMailer < ApplicationMailer
def welcome(user)
@user = user
mail(to: @user.email, subject: 'Welcome!')
end
end
Model’e de bir callback ekleyelim. Artık kullanıcı kayıt olduğunda arka plan görevi olarak bir e-posta atıyoruz.
class User < ApplicationRecord
after_create :send_welcome_mail
private
def send_welcome_mail
UserMailer.welcome(self).deliver_later
end
end
Burada deliver_later
ifadesi oldukça önemli. Böyle diyerek işlemin bir görev olarak kuyruğa girmesini sağlıyoruz. Eğer deliver_now
deseydik kuyruğa girmeden direkt olarak işleme alınacaktı.
UserMailer.welcome(self).deliver_now
UserMailer.welcome(self).deliver_later
Görev (Job) Oluşturma
Sistemimizde kullanıcılar satın aldıkları aboneliklere uygun şekilde bir pasif olma tarihine sahip olsun. Yani örneğin kullanıcı 10 Ağustos tarihine kadar abone olup parasını ödemiş olsun. Bu tarihte artık pasif hale getirilmesi gerekir.
Bunun için bir görev yaratalım.
rails generate job users_clean
class UsersCleanJob < ApplicationJob
queue_as :default
def perform(*args)
# Do something later
end
end
Bunu tetiklemek için
GuestsCleanupJob.perform_later(@user)
Bizim tetikleme tarihimiz belli olduğu için
GuestsCleanupJob.set(wait_until: @user.expire_date).perform_later(@user)
Görevlere Callbacks eklemek
Görevlere de aynı modellerde yaptığımız gibi callback eklenebilir.
class GuestsCleanupJob < ApplicationJob
queue_as :default
around_perform :around_cleanup
def perform
# Do something later
end
private
def around_cleanup
# Do something before perform
yield
# Do something after perform
end
end
Diğer callback’ler de aynı model’deki gibidir.
- before_enqueue
- around_enqueue
- after_enqueue
- before_perform
- around_perform
- after_perform