Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: keypup-io/cloudtasker
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.4.0
Choose a base ref
...
head repository: keypup-io/cloudtasker
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.5.0
Choose a head ref
  • 6 commits
  • 10 files changed
  • 1 contributor

Commits on Nov 25, 2019

  1. fix batch completed event

    Arnaud Lachaume committed Nov 25, 2019
    Copy the full SHA
    82a045c View commit details
  2. update rails example

    Arnaud Lachaume committed Nov 25, 2019
    Copy the full SHA
    2aa9e61 View commit details
  3. switch to lock key prefix

    Arnaud Lachaume committed Nov 25, 2019
    Copy the full SHA
    2472e85 View commit details
  4. lock change operations

    Arnaud Lachaume committed Nov 25, 2019
    Copy the full SHA
    54dbbe8 View commit details
  5. cleaner key namespacing

    Arnaud Lachaume committed Nov 25, 2019
    Copy the full SHA
    e803567 View commit details
  6. bump version

    Arnaud Lachaume committed Nov 25, 2019
    Copy the full SHA
    a271086 View commit details
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
cloudtasker (0.4.0)
cloudtasker (0.5.0)
activesupport
fugit
google-cloud-tasks
15 changes: 15 additions & 0 deletions examples/rails/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.5.5'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.0.rc1'

# Background jobs via Cloud Tasks
gem 'cloudtasker', path: '../../'

# Active record adapter
gem 'sqlite3'
205 changes: 205 additions & 0 deletions examples/rails/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
PATH
remote: ../..
specs:
cloudtasker (0.4.0)
activesupport
fugit
google-cloud-tasks
jwt
redis

GEM
remote: https://rubygems.org/
specs:
actioncable (6.0.1)
actionpack (= 6.0.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.0.1)
actionpack (= 6.0.1)
activejob (= 6.0.1)
activerecord (= 6.0.1)
activestorage (= 6.0.1)
activesupport (= 6.0.1)
mail (>= 2.7.1)
actionmailer (6.0.1)
actionpack (= 6.0.1)
actionview (= 6.0.1)
activejob (= 6.0.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.0.1)
actionview (= 6.0.1)
activesupport (= 6.0.1)
rack (~> 2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.1)
actionpack (= 6.0.1)
activerecord (= 6.0.1)
activestorage (= 6.0.1)
activesupport (= 6.0.1)
nokogiri (>= 1.8.5)
actionview (6.0.1)
activesupport (= 6.0.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.1)
activesupport (= 6.0.1)
globalid (>= 0.3.6)
activemodel (6.0.1)
activesupport (= 6.0.1)
activerecord (6.0.1)
activemodel (= 6.0.1)
activesupport (= 6.0.1)
activestorage (6.0.1)
actionpack (= 6.0.1)
activejob (= 6.0.1)
activerecord (= 6.0.1)
marcel (~> 0.3.1)
activesupport (6.0.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
builder (3.2.3)
concurrent-ruby (1.1.5)
crass (1.0.5)
erubi (1.9.0)
et-orbi (1.2.2)
tzinfo
faraday (0.17.0)
multipart-post (>= 1.2, < 3)
fugit (1.3.3)
et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.1)
globalid (0.4.2)
activesupport (>= 4.2.0)
google-cloud-tasks (1.3.1)
google-gax (~> 1.8)
googleapis-common-protos (>= 1.3.9, < 2.0)
googleapis-common-protos-types (>= 1.0.4, < 2.0)
grpc-google-iam-v1 (~> 0.6.9)
google-gax (1.8.1)
google-protobuf (~> 3.9)
googleapis-common-protos (>= 1.3.9, < 2.0)
googleauth (~> 0.9)
grpc (~> 1.24)
rly (~> 0.2.3)
google-protobuf (3.10.1)
googleapis-common-protos (1.3.9)
google-protobuf (~> 3.0)
googleapis-common-protos-types (~> 1.0)
grpc (~> 1.0)
googleapis-common-protos-types (1.0.4)
google-protobuf (~> 3.0)
googleauth (0.10.0)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.12)
grpc (1.25.0)
google-protobuf (~> 3.8)
googleapis-common-protos-types (~> 1.0)
grpc-google-iam-v1 (0.6.9)
googleapis-common-protos (>= 1.3.1, < 2.0)
grpc (~> 1.0)
i18n (1.7.0)
concurrent-ruby (~> 1.0)
jwt (2.2.1)
loofah (2.3.1)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
memoist (0.16.1)
method_source (0.9.2)
mimemagic (0.3.3)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.13.0)
multi_json (1.14.1)
multipart-post (2.1.1)
nio4r (2.5.2)
nokogiri (1.10.5)
mini_portile2 (~> 2.4.0)
os (1.0.1)
public_suffix (4.0.1)
raabro (1.1.6)
rack (2.0.7)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (6.0.1)
actioncable (= 6.0.1)
actionmailbox (= 6.0.1)
actionmailer (= 6.0.1)
actionpack (= 6.0.1)
actiontext (= 6.0.1)
actionview (= 6.0.1)
activejob (= 6.0.1)
activemodel (= 6.0.1)
activerecord (= 6.0.1)
activestorage (= 6.0.1)
activesupport (= 6.0.1)
bundler (>= 1.3.0)
railties (= 6.0.1)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
railties (6.0.1)
actionpack (= 6.0.1)
activesupport (= 6.0.1)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rake (13.0.1)
redis (4.1.3)
rly (0.2.3)
signet (0.12.0)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
sprockets (4.0.0)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.4.1)
thor (0.20.3)
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.4)
zeitwerk (2.2.1)

PLATFORMS
ruby

DEPENDENCIES
cloudtasker!
rails (~> 6.0.0.rc1)
sqlite3

RUBY VERSION
ruby 2.5.5p157

BUNDLED WITH
2.0.2
17 changes: 9 additions & 8 deletions examples/rails/config/initializers/cloudtasker.rb
Original file line number Diff line number Diff line change
@@ -13,11 +13,12 @@
config.processor_host = 'http://localhost:3000'
end

unless Rails.env.test?
Cloudtasker::Cron::Schedule.load_from_hash!(
'my_worker' => {
'worker' => 'CronWorker',
'cron' => '* * * * *'
}
)
end
#
# Setup cron job
#
# Cloudtasker::Cron::Schedule.load_from_hash!(
# 'my_worker' => {
# 'worker' => 'CronWorker',
# 'cron' => '* * * * *'
# }
# )
11 changes: 6 additions & 5 deletions lib/cloudtasker/batch/job.rb
Original file line number Diff line number Diff line change
@@ -7,7 +7,8 @@ class Job
attr_reader :worker

# Key Namespace used for object saved under this class
SUB_NAMESPACE = 'job'
JOBS_NAMESPACE = 'jobs'
STATES_NAMESPACE = 'states'

# List of statuses triggering a completion callback
COMPLETION_STATUSES = %w[completed dead].freeze
@@ -32,7 +33,7 @@ def self.find(worker_id)
return nil unless worker_id

# Retrieve related worker
payload = redis.fetch(key(worker_id))
payload = redis.fetch(key("#{JOBS_NAMESPACE}/#{worker_id}"))
worker = Cloudtasker::Worker.from_hash(payload)
return nil unless worker

@@ -140,7 +141,7 @@ def batch_id
# @return [String] The worker namespaced id.
#
def batch_gid
key(batch_id)
key("#{JOBS_NAMESPACE}/#{batch_id}")
end

#
@@ -149,7 +150,7 @@ def batch_gid
# @return [String] The batch state namespaced id.
#
def batch_state_gid
[batch_gid, 'state'].join('/')
key("#{STATES_NAMESPACE}/#{batch_id}")
end

#
@@ -371,7 +372,7 @@ def execute
setup

# Complete batch
complete(:success)
complete(:completed)
rescue DeadWorkerError => e
complete(:dead)
raise(e)
18 changes: 11 additions & 7 deletions lib/cloudtasker/cron/schedule.rb
Original file line number Diff line number Diff line change
@@ -72,8 +72,10 @@ def self.load_from_hash!(hash)
# @return [Cloudtasker::Cron::Schedule] The schedule instance.
#
def self.create(**opts)
config = find(opts[:id]).to_h.merge(opts)
new(config).tap(&:save)
redis.with_lock(key(opts[:id])) do
config = find(opts[:id]).to_h.merge(opts)
new(config).tap(&:save)
end
end

#
@@ -95,12 +97,14 @@ def self.find(id)
# @param [String] id The schedule id.
#
def self.delete(id)
schedule = find(id)
return false unless schedule
redis.with_lock(key(id)) do
schedule = find(id)
return false unless schedule

# Delete task and stored schedule
CloudTask.delete(schedule.task_id) if schedule.task_id
redis.del(schedule.gid)
# Delete task and stored schedule
CloudTask.delete(schedule.task_id) if schedule.task_id
redis.del(schedule.gid)
end
end

#
4 changes: 2 additions & 2 deletions lib/cloudtasker/redis_client.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ module RedisClient
module_function

# Suffix added to cache keys when locking them
LOCK_KEY_SUFFIX = 'lock'
LOCK_KEY_PREFIX = 'cloudtasker/lock'

#
# Return the underlying redis client.
@@ -61,7 +61,7 @@ def with_lock(cache_key)
return nil unless cache_key

# Wait to acquire lock
lock_key = [cache_key, LOCK_KEY_SUFFIX].join('/')
lock_key = [LOCK_KEY_PREFIX, cache_key].join('/')
true until client.setnx(lock_key, true)

# yield content
2 changes: 1 addition & 1 deletion lib/cloudtasker/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Cloudtasker
VERSION = '0.4.0'
VERSION = '0.5.0'
end
8 changes: 4 additions & 4 deletions spec/cloudtasker/batch/job_spec.rb
Original file line number Diff line number Diff line change
@@ -133,13 +133,13 @@
describe '#batch_gid' do
subject { batch.batch_gid }

it { is_expected.to eq(described_class.key(batch.batch_id)) }
it { is_expected.to eq(batch.key("#{described_class::JOBS_NAMESPACE}/#{batch.batch_id}")) }
end

describe 'batch_state_gid' do
subject { batch.batch_state_gid }

it { is_expected.to eq([batch.batch_gid, 'state'].join('/')) }
it { is_expected.to eq(batch.key("#{described_class::STATES_NAMESPACE}/#{batch.batch_id}")) }
end

describe '#jobs' do
@@ -532,15 +532,15 @@
context 'with parent_batch' do
after { expect(parent_batch).to have_received(:update_state).with(batch.batch_id, :processing) }
after { expect(batch).to have_received(:setup) }
after { expect(batch).to have_received(:complete).with(:success) }
after { expect(batch).to have_received(:complete).with(:completed) }
it { expect { |b| batch.execute(&b) }.to yield_control }
end

context 'with no parent batch' do
let(:parent_batch) { nil }

after { expect(batch).to have_received(:setup) }
after { expect(batch).to have_received(:complete).with(:success) }
after { expect(batch).to have_received(:complete).with(:completed) }
it { expect { |b| batch.execute(&b) }.to yield_control }
end

2 changes: 1 addition & 1 deletion spec/cloudtasker/redis_client_spec.rb
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@

describe '#with_lock' do
let(:key) { 'cache-key' }
let(:lock_key) { 'cache-key/lock' }
let(:lock_key) { 'cloudtasker/lock/cache-key' }

before { allow(described_class.client).to receive(:setnx).with(lock_key, true).and_return(true) }
after { expect(described_class.client).to have_received(:setnx) }