Belajar Ruby on Rails - Active Job & Action Mailer
Episode 11 of 27

Belajar Ruby on Rails - Active Job & Action Mailer

Membedah Active Job dan Action Mailer: latar belakang kerja asinkron, queue adapters seperti Solid Queue dan Sidekiq, background jobs, mailer dengan template & delivery options, plus praktik notifikasi email async

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 10 kalian melindungi aplikasi dengan test, episode 11 membahas pekerjaan yang tidak boleh memblokir respons HTTP: background jobs (Active Job) dan email (Action Mailer). Dua hal ini hampir selalu berjalan beriringan — mengirim email adalah contoh klasik kerja lambat yang sebaiknya asinkron.

Mengapa penting dikuasai? Karena di aplikasi nyata, hal-hal seperti mengirim email ke ribuan user, memproses gambar, atau memanggil API eksternal tidak boleh membuat user menunggu. Memindahkan kerja berat ke background queue membuat respons cepat dan pengalaman pengguna mulus. Dan email yang terkirim dengan benar adalah tulang punggung komunikasi aplikasi — verifikasi, reset password, notifikasi.

Mengapa Background Job

Bayangkan user klik "simpan" lalu harus menunggu 10 detik karena app menghubungi API eksternal yang lambat. Itulah yang dihindari background job:

100%

Request selesai secepat save data; kerja berat (email, API, resizing gambar) dikerjakan worker di luar request. User mendapat respons instan, dan jika worker crash, job tetap antri dan bisa diulang.

Active Job: API Seragam

Active Job adalah antarmuka umum untuk semua backend queue. Job hanyalah class Ruby:

Generate job
bin/rails g job ProcessReport
Rubyapp/jobs/process_report_job.rb
class ProcessReportJob < ApplicationJob
  queue_as :default
 
  def perform(report_id)
    report = Report.find(report_id)
    rows = report.generate_rows
    ReportExporter.export(rows)
  end
end

Dijalankan di mana pun:

RubyEnqueue job
ProcessReportJob.perform_later(report.id)
ProcessReportJob.set(wait: 5.minutes).perform_later(report.id)
ProcessReportJob.perform_now(report.id)  # sinkron, untuk debug

perform_later menaruh job ke queue; set(wait:) menjadwalkan. Kode yang memanggil job tidak peduli backend apa yang dipakai — Active Job menyembunyikannya.

Queue Adapters

Rails 8 memakai Solid Queue secara default — queue berbasis database, tanpa layanan tambahan:

Rubyconfig/environments/production.rb
config.active_job.queue_adapter = :solid_queue

Untuk kebutuhan throughput tinggi, Sidekiq (Redis) adalah pilihan klasik:

RubySidekiq
config.active_job.queue_adapter = :sidekiq
AdapterBackendKelebihanKekurangan
Solid QueuePostgreSQL/MySQLTanpa infra tambahan, transactional, sudah default Rails 8Kinerja menengah untuk volume sangat besar
SidekiqRedisSangat cepat, UI monitoringButuh Redis; job bisa hilang saat Redis crash tanpa mode pro
Async (dev)In-processMudah untuk developmentTidak bertahan restart

Action Mailer

Action Mailer adalah modul email Rails. Mailer adalah class seperti controller, dengan view sendiri:

Generate mailer
bin/rails g mailer PostMailer post_published
Rubyapp/mailers/post_mailer.rb
class PostMailer < ApplicationMailer
  def post_published(user, post)
    @user = user
    @post = post
 
    mail(to: user.email, subject: "Post baru terbit: #{post.title}")
  end
end

Template email di app/views/post_mailer/ — versi teks dan HTML:

HTMLapp/views/post_mailer/post_published.html.erb
<h1>Halo <%= @user.name %></h1>
<p>Post terbaru telah terbit: <%= link_to @post.title, @post %></p>

Delivery Options

Konfigurasi delivery di environment:

Rubyconfig/environments/development.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address: "smtp.example.com", port: 587,
  user_name: Rails.application.credentials.smtp[:user],
  password: Rails.application.credentials.smtp[:password]
}

Di development, config.action_mailer.raise_delivery_errors = true membuat error email langsung terlihat. Tools seperti Letter Opener menampilkan email di browser tanpa mengirim sungguhan.

Praktik: Notifikasi Email Async

Kombinasi mailer + job adalah pola paling umum. Kita bungkus pengiriman di job agar tidak memblokir request:

Rubyapp/jobs/post_notification_job.rb
class PostNotificationJob < ApplicationJob
  def perform(post_id)
    post = Post.find(post_id)
    User.where(subscribed: true).each do |user|
      PostMailer.post_published(user, post).deliver_now
    end
  end
end

Controller hanya mengantri:

RubyEnqueue dari controller
def create
  @post = Post.new(post_params)
  if @post.save
    PostNotificationJob.perform_later(@post.id)
    redirect_to @post, notice: "Post terbit. Email sedang dikirim."
  else
    render :new, status: :unprocessable_entity
  end
end

Pola ini membuat response cepat; pengiriman ribuan email berjalan di worker. Untuk email per-user lebih baik kirim per-user di dalam loop job (bukan satu job raksasa) agar satu kegagalan tidak menggagalkan semua.

Menjalankan Worker di Development

Job tidak berjalan otomatis di development; worker harus dijalankan:

Jalankan worker Solid Queue
bin/rails solid_queue:start

Di production, bin/rails solid_queue:start dijalankan sebagai proses terpisah (dibahas di episode 22 & 24). Lupa menjalankan worker adalah alasan paling umum "email tidak terkirim di development".

Warning

Jangan memanggil API eksternal atau mengirim email sinkron di dalam request kecuali benar-benar diperlukan. Response jadi lambat, dan jika proses crash di tengah jalan, kerja hilang tanpa jejak. Background job memberi retry otomatis dan audit trail.

Common Pitfalls

  • Job memakai data yang sudah diubahperform(post_id) lalu fetch dari DB (bukan meneruskan objek), agar job memakai snapshot terkini dan aman di-serialize.
  • Email exception menghentikan semua — bungkus per-item dalam rescue/retry_on agar satu kegagalan tidak membatalkan batch.
  • deliver_now untuk volume besar di dalam request — gunakan job; deliver_later menempatkan ke queue.
  • Sidekiq tanpa retry policy eksplisit — default retry 25x bisa menumpuk; atur retry_on/max retry sesuai kebutuhan.

Penutup

Episode 11 membekali kalian kerja asinkron Rails: Active Job sebagai API seragam, Solid Queue default database-driven vs Sidekiq untuk throughput tinggi, Action Mailer dengan template teks/HTML dan SMTP settings, serta pola notifikasi email yang dienkue dari controller agar response tetap cepat.

Inti yang harus dibawa pulang:

  • Background job memindahkan kerja berat keluar dari request → response cepat.
  • Active Job: perform_later untuk async, set(wait:) untuk jadwal.
  • Solid Queue (default Rails 8) berbasis database; Sidekiq untuk volume besar.
  • Action Mailer: mailer class + template HTML/teks + delivery via SMTP.
  • Pola kunci: controller mengantri job, job mengirim email per-user.

Di episode 12 selanjutnya kita akan membedah caching & performance — fragment/page caching, Russian Doll caching, low-level cache, cache stores (Redis, Solid Cache), serta optimasi query N+1 dengan includes/joins. Sampai jumpa di episode 12!

Belajar Ruby on Rails - Active Job & Action Mailer | Belajar Ruby on Rails