Last active
January 13, 2022 02:14
-
-
Save nhocki/323eeaa5deeb09a0bb11439dd61b30d2 to your computer and use it in GitHub Desktop.
Most naive worker autoscaler for Heroku.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Autoscaler | |
def initialize(app_name:, token: ENV["AUTOSCALE_TOKEN"]) | |
@client = PlatformAPI.connect_oauth(token) | |
@app_name = app_name | |
end | |
def run! | |
puts "[Autoscaler] We currently have #{current_number_of_workers} workers and #{number_of_queued_jobs} jobs queued." | |
if number_of_queued_jobs > 0 && current_number_of_workers < 1 | |
puts "[Autoscaler] We have queued jobs & no workers! Scaling up!" | |
scale_workers(1) | |
elsif number_of_queued_jobs.zero? && current_number_of_workers > 0 | |
puts "[Autoscaler] No queued jobs. Removing all workers" | |
scale_workers(0) | |
else | |
puts "[Autoscaler] No action needed!" | |
end | |
end | |
private | |
def number_of_queued_jobs | |
Sidekiq::Queue.all.sum(&:size) | |
end | |
def current_number_of_workers | |
worker_process["quantity"] | |
end | |
def scale_workers(count) | |
if current_number_of_workers == count | |
puts "[Autoscaler] No action needed!" | |
end | |
@client.formation.batch_update( | |
@app_name, | |
updates: [{quantity: count, size: worker_process["size"], type: "worker"}] | |
) | |
puts "[Autoscaler] Done!" | |
end | |
def worker_process | |
@worker_process ||= processes.find { |process| process["type"] == "worker" } | |
end | |
def processes | |
@processes ||= @client.formation.list(@app_name) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Add this to Heroku scheduler to run every 10 minutes: bundle exec rails infrastructure:autoscale_workers | |
namespace :infrastructure do | |
desc "Autoscale sidekiq workers based on currently scheduled jobs" | |
task autoscale_workers: [:environment] do | |
Autoscaler.new(app_name: "your_app_name").run! | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment