Skip to content

Instantly share code, notes, and snippets.

@benoittgt
Created July 24, 2018 13:13
Show Gist options
  • Save benoittgt/224dcfc439dabd94376b8d1ef5f60d56 to your computer and use it in GitHub Desktop.
Save benoittgt/224dcfc439dabd94376b8d1ef5f60d56 to your computer and use it in GitHub Desktop.
refactor Remi worker
# from https://twitter.com/mercier_remi/status/1021669831190433792
class CreateNotificationsWorker
include Sidekiq::Worker
def perform
users = User.all
users.each do |user|
tasks = user.tasks
tasks.each do |task|
if task.deadline && task.status == 'pending' && task.notified_user == false
@notification = Notification.create!(user_id: user.id, task_id: task.id)
task.notified_user = true
task.save!
end
end
end
end
end
@benoittgt
Copy link
Author

benoittgt commented Jul 24, 2018

  • Line 6 you load all user 💥
  • Line 7 you load all user's task even if you need only the one that are pending, where notified_user is false or where deadline is not nil or false
  • tasks.each load all task. Check .find_each if you can have many tasks.
  • Line 9, if 'pending' is an enum you can instead refer to it as Task.statuses[:pending]
  • Line 10, do you need the @?
  • What happens if save! raise an exception?

Instead you could write (assuming task.deadline need to be not nil, and status an enum)

class CreateNotificationsWorker
  include Sidekiq::Worker
  def perform
    Task.pending.where(user: User.all, notified_user: false).where.not(deadline: nil).find_each do |task|
      Notification.create!(user_id: user.id, task_id: task.id)
      task.notified_user = true
      task.save!
    rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved => exception
      # Notify your bug library like (airbrake, honeybadger...) with the `exception`
      next
    end
  end
end

For the long query you could put into a method.

class CreateNotificationsWorker
  include Sidekiq::Worker
  def perform
    pending_tasks_to_notify.find_each do |task|
      #....
    end
  end

  private
  
  def pending_tasks_to_notify
    Task.pending.where(user: User.all, notified_user: false).where.not(deadline: nil)
  end
end

@merciremi
Copy link

Task.pending => Great idea! I had completely forgotten about these methods associated with enums.
.where.not => Sweet!
find_each=> Sonia talked to me about it yesterday. Really cool way to reduce the load on memory.

Thanks, @benoittgt for all these ameliorations.

I don't use any bug library (not that I'm aware of anyway). Which one would you suggest I should start with?

@benoittgt
Copy link
Author

We use airbrake an are quite happy about it. But honeybadger seems good too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment