taskinator 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 683a1ffedb432057d353d7ebbc31dff766bce83c
4
- data.tar.gz: 92c78c8a6e2c87769269147557c9c2cb13be52fa
3
+ metadata.gz: 2f06333f9729441692c47b0eecc144080b2711ff
4
+ data.tar.gz: 4b6db6e7787af743783a45dea8070813d9d2df9e
5
5
  SHA512:
6
- metadata.gz: d9449a313b53581d06109e16d6f1a268a5f786848fc4d725e0852b773dbe99b1a68898a88c0d077bfb48590b976dbc4ca821e9207f20b50343f924493c35d9aa
7
- data.tar.gz: 5c621a66e20dfef0f7800482ea5dd308c7470393537022791d3398a4f12c9350ca40a89267de82a149adcaf5c8561ae8b6aa732826ab85843e0f330cb701396f
6
+ metadata.gz: 4d352409fcbfce51f8591779c291cee6a2fcecd2513a33d07657c8e85045654af4af639908704e3e9f7fda3c72859781bf36d96c7e4dfdbb48decd3e2a38e161
7
+ data.tar.gz: c849ec329437762c590e2858c794729cf08264343907692ba564a9a7cd5858da7109452c88bb9777299a36726008feea3dfb4201706913be011ad4996c7e0621
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ v0.3.1 - 16 Sep 2015
2
+ ---
3
+ Added redis-semaphore gem, for fix to concurrent processes completion logic.
4
+
1
5
  v0.3.0 - 28 Aug 2015
2
6
  ---
3
7
  Added created_at and updated_at to process and task as attributes.
data/Gemfile.lock CHANGED
@@ -1,6 +1,6 @@
1
1
  GIT
2
2
  remote: git://github.com/mperham/sidekiq.git
3
- revision: b0cdd4cc868e7564b78ee34965067e025ec41689
3
+ revision: 50fc8ee7c3f7c5e4049db598c0e14465a67a877c
4
4
  specs:
5
5
  sidekiq (3.5.0)
6
6
  celluloid (~> 0.17.0)
@@ -12,16 +12,17 @@ GIT
12
12
  PATH
13
13
  remote: .
14
14
  specs:
15
- taskinator (0.3.0)
15
+ taskinator (0.3.1)
16
16
  connection_pool (>= 2.2.0)
17
17
  json (>= 1.8.2)
18
18
  redis (>= 3.2.1)
19
19
  redis-namespace (>= 1.5.2)
20
+ redis-semaphore (>= 0.2.4)
20
21
 
21
22
  GEM
22
23
  remote: https://rubygems.org/
23
24
  specs:
24
- activesupport (4.2.3)
25
+ activesupport (4.2.4)
25
26
  i18n (~> 0.7)
26
27
  json (~> 1.7, >= 1.7.7)
27
28
  minitest (~> 5.1)
@@ -29,7 +30,7 @@ GEM
29
30
  tzinfo (~> 1.1)
30
31
  byebug (5.0.0)
31
32
  columnize (= 0.9.0)
32
- celluloid (0.17.1.1)
33
+ celluloid (0.17.1.2)
33
34
  bundler
34
35
  celluloid-essentials
35
36
  celluloid-extras
@@ -39,37 +40,37 @@ GEM
39
40
  dotenv
40
41
  nenv
41
42
  rspec-logsplit (>= 0.1.2)
42
- timers (~> 4.0.0)
43
- celluloid-essentials (0.20.2)
43
+ timers (>= 4.1.1)
44
+ celluloid-essentials (0.20.2.1)
44
45
  bundler
45
46
  dotenv
46
47
  nenv
47
48
  rspec-logsplit (>= 0.1.2)
48
- timers (~> 4.0.0)
49
- celluloid-extras (0.20.0)
49
+ timers (>= 4.1.1)
50
+ celluloid-extras (0.20.1)
50
51
  bundler
51
52
  dotenv
52
53
  nenv
53
54
  rspec-logsplit (>= 0.1.2)
54
- timers (~> 4.0.0)
55
- celluloid-fsm (0.20.0)
55
+ timers (>= 4.1.1)
56
+ celluloid-fsm (0.20.1)
56
57
  bundler
57
58
  dotenv
58
59
  nenv
59
60
  rspec-logsplit (>= 0.1.2)
60
- timers (~> 4.0.0)
61
- celluloid-pool (0.20.0)
61
+ timers (>= 4.1.1)
62
+ celluloid-pool (0.20.1)
62
63
  bundler
63
64
  dotenv
64
65
  nenv
65
66
  rspec-logsplit (>= 0.1.2)
66
- timers (~> 4.0.0)
67
- celluloid-supervision (0.20.1)
67
+ timers (>= 4.1.1)
68
+ celluloid-supervision (0.20.1.1)
68
69
  bundler
69
70
  dotenv
70
71
  nenv
71
72
  rspec-logsplit (>= 0.1.2)
72
- timers (~> 4.0.0)
73
+ timers (>= 4.1.1)
73
74
  coderay (1.1.0)
74
75
  columnize (0.9.0)
75
76
  connection_pool (2.2.0)
@@ -86,13 +87,13 @@ GEM
86
87
  domain_name (0.5.24)
87
88
  unf (>= 0.0.5, < 1.0.0)
88
89
  dotenv (2.0.2)
89
- hitimes (1.2.2)
90
+ hitimes (1.2.3)
90
91
  http-cookie (1.0.2)
91
92
  domain_name (~> 0.5)
92
93
  i18n (0.7.0)
93
94
  json (1.8.3)
94
95
  method_source (0.8.2)
95
- mime-types (2.6.1)
96
+ mime-types (2.6.2)
96
97
  minitest (5.8.0)
97
98
  mono_logger (1.1.0)
98
99
  multi_json (1.11.2)
@@ -112,6 +113,8 @@ GEM
112
113
  redis (3.2.1)
113
114
  redis-namespace (1.5.2)
114
115
  redis (~> 3.0, >= 3.0.4)
116
+ redis-semaphore (0.2.4)
117
+ redis
115
118
  resque (1.25.2)
116
119
  mono_logger (~> 1.0)
117
120
  multi_json (~> 1.0)
@@ -159,7 +162,7 @@ GEM
159
162
  thor (0.19.1)
160
163
  thread_safe (0.3.5)
161
164
  tilt (2.0.1)
162
- timers (4.0.1)
165
+ timers (4.1.1)
163
166
  hitimes
164
167
  tins (1.6.0)
165
168
  tzinfo (1.2.2)
@@ -222,6 +222,7 @@ module Taskinator
222
222
  end
223
223
  end
224
224
 
225
+ # this method only called in-process (usually from the console)
225
226
  def start
226
227
  if tasks.empty?
227
228
  complete! # weren't any tasks to start with
@@ -247,7 +248,17 @@ module Taskinator
247
248
  def task_completed(task)
248
249
  # when complete on first, then don't bother with subsequent tasks completing
249
250
  return if completed? || failed?
250
- complete!
251
+
252
+ if tasks_completed?
253
+ # prevent re-entrance so that two tasks completing
254
+ # simultaneously can't complete the process twice,
255
+ # which enqueues/starts the same subsequent task
256
+ Taskinator.redis_mutex(uuid) do
257
+ # double check, since the status may have
258
+ # changed while waiting in the mutex
259
+ complete! if tasks_completed?
260
+ end
261
+ end
251
262
  end
252
263
 
253
264
  def tasks_completed?
@@ -1,3 +1,3 @@
1
1
  module Taskinator
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -2,7 +2,8 @@ module Taskinator
2
2
  module Workflow
3
3
 
4
4
  def current_state
5
- @current_state ||= load_workflow_state
5
+ # NB: don't memoize this value (i.e. re-read it each time)
6
+ @current_state = load_workflow_state
6
7
  end
7
8
 
8
9
  def current_state=(new_state)
data/lib/taskinator.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'json'
2
2
  require 'yaml'
3
3
  require 'securerandom'
4
+ require 'redis-semaphore'
4
5
 
5
6
  require 'taskinator/version'
6
7
 
@@ -62,6 +63,13 @@ module Taskinator
62
63
  redis_pool.with(&block)
63
64
  end
64
65
 
66
+ def redis_mutex(lockid, options={}, &block)
67
+ raise ArgumentError, "requires a block" unless block_given?
68
+ redis do |r|
69
+ Redis::Semaphore.new(lockid, {:redis => r}.merge(options)).lock(&block)
70
+ end
71
+ end
72
+
65
73
  def redis_pool
66
74
  @redis ||= Taskinator::RedisConnection.create
67
75
  end
@@ -344,7 +344,9 @@ describe Taskinator::Process do
344
344
 
345
345
  describe Taskinator::Process::Concurrent do
346
346
 
347
- subject { Taskinator::Process.define_concurrent_process_for(definition) }
347
+ let(:complete_on) { Taskinator::CompleteOn::Default }
348
+
349
+ subject { Taskinator::Process.define_concurrent_process_for(definition, complete_on) }
348
350
 
349
351
  it_should_behave_like "a process", Taskinator::Process::Concurrent do
350
352
 
@@ -414,12 +416,33 @@ describe Taskinator::Process do
414
416
  end
415
417
 
416
418
  describe "#task_completed" do
417
- it "completes when tasks complete" do
418
- tasks.each {|t| subject.tasks << t }
419
+ it "completes when tasks complete (CompleteOn::First)" do
420
+ allow_any_instance_of(Taskinator::Task).to receive(:completed?) { true }
419
421
 
420
- expect(subject).to receive(:complete!)
422
+ process = Taskinator::Process.define_concurrent_process_for(definition, Taskinator::CompleteOn::First)
423
+ tasks.each {|t| process.tasks << t }
424
+
425
+ expect(process).to receive(:complete!).and_call_original
426
+
427
+ process.task_completed(tasks.first)
428
+
429
+ # remaining tasks should do nothing...
430
+ tasks.each do |task|
431
+ process.task_completed(task)
432
+ end
433
+ end
434
+
435
+ it "completes when tasks complete (CompleteOn::Last)" do
436
+ allow_any_instance_of(Taskinator::Task).to receive(:completed?) { true }
421
437
 
422
- subject.task_completed(tasks.first)
438
+ process = Taskinator::Process.define_concurrent_process_for(definition, Taskinator::CompleteOn::Last)
439
+ tasks.each {|t| process.tasks << t }
440
+
441
+ expect(process).to receive(:complete!).and_call_original
442
+
443
+ tasks.each do |task|
444
+ process.task_completed(task)
445
+ end
423
446
  end
424
447
  end
425
448
 
data/taskinator.gemspec CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  # core
24
24
  spec.add_dependency 'redis' , '>= 3.2.1'
25
25
  spec.add_dependency 'redis-namespace' , '>= 1.5.2'
26
+ spec.add_dependency 'redis-semaphore' , '>= 0.2.4'
26
27
  spec.add_dependency 'connection_pool' , '>= 2.2.0'
27
28
  spec.add_dependency 'json' , '>= 1.8.2'
28
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taskinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Stefano
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-01 00:00:00.000000000 Z
11
+ date: 2015-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.5.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis-semaphore
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.2.4
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.2.4
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: connection_pool
43
57
  requirement: !ruby/object:Gem::Requirement