Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic CloudScheduler implementation #71

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cloudtasker.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'connection_pool'
spec.add_dependency 'fugit'
spec.add_dependency 'google-cloud-tasks'
spec.add_dependency 'google-cloud-scheduler'
spec.add_dependency 'jwt'
spec.add_dependency 'redis'
spec.add_dependency 'retriable'
Expand Down
6 changes: 6 additions & 0 deletions lib/cloudtasker/cloud_scheduler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

module Cloudtasker
module CloudScheduler
end
end
96 changes: 96 additions & 0 deletions lib/cloudtasker/cloud_scheduler/manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
require "google/cloud/scheduler"
module Cloudtasker
module CloudScheduler
class Manager
class << self
def synchronize!(file)
new(YAML.load_file(file)).synchronize!
end
end

attr_reader :client, :cron_config

def initialize(cron_config = {})
@client = Google::Cloud::Scheduler.cloud_scheduler
@cron_config = cron_config
end

def synchronize!
remote_list_names = remote_list.map(&:name).select{|x| x.start_with?(job_prefix) }
puts "Creating/updating jobs"
if local_list.present?
local_list.each do |job|
if job[:name].in?(remote_list_names)
client.update_job(job: job)
else
puts "Creating #{job[:name]}"
client.create_job(parent: parent, job: job)
end
end
end

local_list_names = local_list.map{|x| x[:name] }
delete_jobs = (remote_list_names - local_list_names)

if delete_jobs.present?
puts "Deleting jobs"
delete_jobs.each do |name|
puts "Deleting #{name}"
client.delete_job(name: name)
end
end

true
end

private

def local_list
cron_config.map do |name, job_config|
build_job(name, job_config)
end
end

def remote_list
client.list_jobs(parent: parent).response.jobs
end


def job_prefix
"#{parent}/jobs/#{config.gcp_queue_prefix}--"
end

def job_name(name)
"#{job_prefix}#{name}"
end

def build_job(name, job_config)
request = Cloudtasker::WorkerHandler.new(job_config["worker"].constantize.new).task_payload[:http_request]
{
name: job_name(name),
schedule: job_config["cron"],
time_zone: job_config["time_zone"] || 'UTC',
http_target: {
uri: request[:url],
http_method: request[:http_method],
headers: request[:headers],
body: request[:body]
}
}
end

def parent
client.location_path(project: config.gcp_project_id, location: config.gcp_location_id)
end

#
# Return the cloudtasker configuration. See Cloudtasker#configure.
#
# @return [Cloudtasker::Config] The library configuration.
#
def config
Cloudtasker.config
end
end
end
end
12 changes: 12 additions & 0 deletions lib/tasks/setup_cloud_scheduler.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

ENV['GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS'] ||= 'true'

namespace :cloudtasker do
DEFAULT_FILE = 'config/cloudtasker_cron.yml'

desc "Setup CloudScheduler. (default options: file=#{DEFAULT_FILE})"
task setup_cloud_scheduler: :environment do
Cloudtasker::CloudScheduler::Manager.synchronize!(DEFAULT_FILE)
end
end