Skip to content

Instantly share code, notes, and snippets.

@kirkland
Last active May 18, 2016 20:44
Show Gist options
  • Save kirkland/eb3902d4d60c43f8b9a9657448fc5e7d to your computer and use it in GitHub Desktop.
Save kirkland/eb3902d4d60c43f8b9a9657448fc5e7d to your computer and use it in GitHub Desktop.
Delayed::Backend::ActiveRecord::Job.class_eval do
def self.build_ready_scope(worker, max_run_time)
ready_scope = ready_to_run(worker.name, max_run_time)
ready_scope = ready_scope.by_priority
ready_scope = ready_scope.where(
RandomUserIdQuery::SQL, db_time_now: db_time_now,
worker_name: worker.name,
locked_at_expired_at: db_time_now - max_run_time
)
ready_scope
end
def self.reserve(worker, max_run_time = Delayed::Worker.max_run_time)
reserve_with_scope(build_ready_scope(worker, max_run_time), worker, db_time_now)
end
end
class RandomUserIdQuery
def generate_sql
<<-EOSQL
user_id =
(
WITH
#{top_priority_cte},
#{eligible_user_ids_cte}
SELECT user_id
FROM eligible_user_ids
ORDER BY random()
LIMIT 1
)
EOSQL
end
private
# A job is runnable if it isn't locked or permanently failed, and the run_at time is not in the future
def runnable_filter
<<-EOSQL
(
run_at <= :db_time_now
AND (locked_at IS NULL OR locked_at < :locked_at_expired_at)
OR locked_by = :worker_name
)
AND failed_at IS NULL
AND "delayed_jobs"."blocked" = 'f'
EOSQL
end
# Calculate the highest priority among runnable jobs
def top_priority_cte
<<-EOSQL
top_priority AS
(
SELECT MIN(priority) AS top_priority
FROM delayed_jobs
WHERE #{runnable_filter}
)
EOSQL
end
def priority_filter
'delayed_jobs.priority = (SELECT top_priority FROM top_priority)'
end
# Only consider users that have a currently-runnable job and that has the highest priority among jobs
def eligible_user_ids_cte
<<-EOSQL
eligible_user_ids AS
(
SELECT DISTINCT user_id
FROM delayed_jobs
WHERE #{runnable_filter} AND #{priority_filter}
)
EOSQL
end
# We only need to generate this SQL once, the first time this file is loaded
SQL = new.generate_sql.freeze
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment