Monday, May 13, 2024
HomeRuby On RailsBroadcasting Progress from Background Jobs

Broadcasting Progress from Background Jobs


# Terminal
rails g controller heavy_tasks
rails g job heavy_tasks
rails g job small_task
rails g stimulus progress-bar
# config/routes.rb
sources :heavy_tasks, solely: :create
# app/controllers/heavy_tasks_controller.rb
class HeavyTasksController < ApplicationController
  before_action :authenticate_user!

  def create
    HeavyTaskJob.perform_later(current_user.id)
  finish
finish
# app/jobs/heavy_task_job.rb
class HeavyTaskJob < ApplicationJob
  queue_as :default
  before_perform :broadcast_initial_update

  def carry out(current_user_id)

    total_count.instances do |i|
      SmallTaskJob.perform_later(current_user_id, i, total_count)
    finish
  finish

  non-public

  def broadcast_initial_update
    Turbo::StreamsChannel.broadcast_replace_to ["heavy_task_channel", current_user.to_gid_param].be part of(":"),
      goal: "heavy_task",
      partial: "heavy_tasks/progress",
      locals: {
        total_count: total_count
      }
  finish

  def total_count
    @total_count ||= rand(10..100)
  finish

  def current_user
    @current_user ||= Person.discover(self.arguments.first)
  finish
finish
# app/jobs/small_task_job.rb
class SmallTaskJob < ApplicationJob
  queue_as :default

  def carry out(current_user_id, i, total_count)
    current_user = Person.discover(current_user_id)
    sleep rand
    # Turbo::StreamsChannel.broadcast_replace_to ["heavy_task_channel", current_user.to_gid_param].be part of(":"),
    #   goal: "heavy_task",
    #   partial: "heavy_tasks/progress",
    #   locals: {
    #     progress: (i + 1) * 100 / total_count
    #   }

    Turbo::StreamsChannel.broadcast_action_to ["heavy_task_channel", current_user.to_gid_param].be part of(":"),
      motion: "append",
      goal: "heavy_task",
      content material: "<div></div>"
  finish
finish
# app/views/welcome/index.html.erb
<%= render partial: "heavy_tasks/button" %>
# app/views/heavy_tasks/_button.html.erb
<%= turbo_stream_from ["heavy_task_channel", current_user] if user_signed_in? %>

<div id="heavy_task">
  <%= button_to "Carry out Heavy Job", heavy_tasks_path, class: "btn btn-primary" %>
</div>
# app/views/heavy_tasks/_progress.html.erb
<div id="heavy_task"
  data-controller="progress-bar"
  data-progress-bar-total-jobs-value="<%= total_count %>">
  <div class="progress">
    <div class="progress-bar progress-bar-striped energetic"
      position="progressbar"
      data-progress-bar-target="progress">
  </div>
</div>
# app/javascript/controllers/progress_bar_controller.js
import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="progress-bar"
export default class extends Controller {
  static values = {
    totalJobs: 0,
    completedJobs: 0
  }
  static targets = ["progress"]
  join() {
    this.observer = new MutationObserver((mutationsList, _observer) => {
      for (let mutation of mutationsList) {
        if (mutation.sort === 'childList') {
          this.increment()
        }
      }
    })

    this.observer.observe(this.ingredient, { childList: true })
  }

  increment() {
    this.completedJobsValue++
    this.updateProgress()
  }

  updateProgress() {
    let progress = (this.completedJobsValue / this.totalJobsValue) * 100
    this.progressTarget.fashion.width = `${progress}%`
  }
}
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments