TLDR;
Lot of times we can avoid enqueuing the jobs to the background queue if they are going to be discarded immediately upon execution.
Let's say we have a background job to send a webhook notification to Slack.
# app/services/events_service.rb
class EventsService
def process
@event = create_event
SlackJob.perform_later(@org, @event)
end
end
# app/jobs/slack_job.rb
class SlackJob < ApplicationJob
def perform(org, payload)
if org.slack_enabled?
SendSlackNotification.new(org, payload).process
end
end
end
The job is enqueued for sending the notification and then inside the job we are checking if the organization has enabled slack or not. Only if slack is enabled then the job will be executed. But it still gets enqueued in the queue and the worker process has to pick it up and start executing. Only then it realizes that the job does not satisfy required conditions and discards it.
This means that each time the SlackJob gets enqueued and gets picked up for execution by the worker process.
A better approach will be to enqueue only the jobs that are going to be actually executed. This will avoid unnecessarily enqueuing jobs which are going to be discarded immediately.
# app/services/events_service.rb
class EventsService
def process
@event = create_event
if @org.slack_enabled?
SlackJob.perform_later(@org, @event)
end
end
end
# app/jobs/slack_job.rb
class SlackJob < ApplicationJob
def perform(org, payload)
SendSlackNotification.new(org, payload).process
end
end
This pattern should be used in cases where the decision of whether to execute the job or not too complex and does not depend on too many entities. If the job has to take decision based on complex logic then it can he handled in the job itself instead of doing it before enqueuing the job. But for simple conditionals, we can check them beforehand to avoid enqueuing of the job and immediately discarding.
Interested in knowing more about my thoughts on web programming using Ruby on Rails? Subscribe here or follow me on Twitter.
Top comments (0)