shoryuken-later 0.0.5.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ddee2c4f752e577a58318adb619953bb2f59481
4
- data.tar.gz: 15ceff15183b969a80c881efa19ad7682e2b70df
3
+ metadata.gz: 4ed2b69dae97667b38ef15a0be1ee0f6989e9c95
4
+ data.tar.gz: 82fa4cb2cb2f763be48094df3f4224a025d56815
5
5
  SHA512:
6
- metadata.gz: 773be98b8d0268b9d44be8186ce3e3762c33ab7d220fcb14d196c8a781156a5e7bc45189c8d55cd55ace3c6c7666a0ae0c617d9dfd4625ec0048d41132a76a29
7
- data.tar.gz: b529a8387cde89f23e8ed5dffd489498eb0e024a82195f5732fb366fe2529369ab83a9c4af4eadf7780c106e107ea188bb5961a783debdd09f52f0398af3fdee
6
+ metadata.gz: 9f1d6efd2b3521a763e685e65d3c695fa8282ab6f3b0b4b0dc6450d26a0b656ffffaf40057db9bf35cee63ac1f9708715649581ff0094ddf2d0bd707a195cf02
7
+ data.tar.gz: f5f07fd722f05fc37206b8e4a59e1acf2960282a7656d60275df746458b60bbf0b3be0e2e82d649fd5ae4fefc0875025cfd84d4e839bb45927c20f38453d706a
data/Rakefile CHANGED
File without changes
@@ -7,6 +7,7 @@ require 'singleton'
7
7
  require 'optparse'
8
8
  require 'erb'
9
9
  require 'shoryuken/later'
10
+ require 'timers'
10
11
 
11
12
  module Shoryuken
12
13
  module Later
@@ -14,8 +15,6 @@ module Shoryuken
14
15
  include Shoryuken::Util
15
16
  include Singleton
16
17
 
17
- attr_accessor :launcher
18
-
19
18
  def run(args)
20
19
  self_read, self_write = IO.pipe
21
20
 
@@ -34,38 +33,47 @@ module Shoryuken
34
33
  validate!
35
34
  daemonize
36
35
  write_pid
37
- load_celluloid
38
-
39
- require 'shoryuken/later/launcher'
40
- @launcher = Shoryuken::Later::Launcher.new
41
-
36
+
37
+ logger.info 'Starting'
38
+
39
+ # Initialize the timers and poller.
40
+ @timers = Timers::Group.new
41
+ require 'shoryuken/later/poller'
42
+ @pollers = Shoryuken::Later.tables.map{|tbl| Poller.new(tbl) }
43
+
42
44
  begin
43
- launcher.run
44
-
45
- while readable_io = IO.select([self_read])
46
- signal = readable_io.first[0].gets.strip
47
- handle_signal(signal)
45
+ # Poll for items on startup, and every :poll_delay
46
+ poll_tables
47
+ @timers.every(Shoryuken::Later.poll_delay){ poll_tables }
48
+
49
+ # Loop watching for signals and firing off of timers
50
+ loop do
51
+ interval = @timers.wait_interval
52
+ readable, writable = IO.select([self_read], nil, nil, interval)
53
+ if readable
54
+ handle_signal readable.first.gets.strip
55
+ else
56
+ @timers.fire
57
+ end
48
58
  end
49
59
  rescue Interrupt
50
- launcher.stop(shutdown: true)
60
+ @timers.cancel
51
61
  exit 0
52
62
  end
53
63
  end
64
+
65
+ protected
66
+
67
+ def poll_tables
68
+ logger.debug "Polling schedule tables"
69
+ @pollers.each do |poller|
70
+ poller.poll
71
+ end
72
+ logger.debug "Polling done"
73
+ end
54
74
 
55
75
  private
56
76
 
57
- def load_celluloid
58
- raise "Celluloid cannot be required until here, or it will break Shoryuken::Later's daemonization" if defined?(::Celluloid) && Shoryuken::Later.options[:daemon]
59
-
60
- # Celluloid can't be loaded until after we've daemonized
61
- # because it spins up threads and creates locks which get
62
- # into a very bad state if forked.
63
- require 'celluloid/autostart'
64
- Celluloid.logger = (Shoryuken::Later.options[:verbose] ? Shoryuken::Later.logger : nil)
65
-
66
- require 'shoryuken/later/manager'
67
- end
68
-
69
77
  def load_rails
70
78
  # Adapted from: https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/cli.rb
71
79
 
@@ -182,28 +190,11 @@ module Shoryuken
182
190
  case sig
183
191
  when 'USR1'
184
192
  logger.info "Received USR1, will soft shutdown down"
185
-
186
- launcher.stop
187
-
193
+ @timers.cancel
194
+ sleep 1 while @busy
188
195
  exit 0
189
- when 'TTIN'
190
- Thread.list.each do |thread|
191
- logger.info "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
192
- if thread.backtrace
193
- logger.info thread.backtrace.join("\n")
194
- else
195
- logger.info "<no backtrace available>"
196
- end
197
- end
198
-
199
- idle = launcher.manager.instance_variable_get(:@idle).size
200
- busy = launcher.manager.instance_variable_get(:@busy).size
201
- tables = launcher.manager.instance_variable_get(:@tables)
202
-
203
- logger.info "Idle: #{idle}, Busy: #{busy}, Polled Tables: #{tables.join(', ')}"
204
196
  else
205
197
  logger.info "Received #{sig}, will shutdown down"
206
-
207
198
  raise Interrupt
208
199
  end
209
200
  end
@@ -3,16 +3,12 @@ require 'json'
3
3
  module Shoryuken
4
4
  module Later
5
5
  class Poller
6
- include Celluloid
7
6
  include Shoryuken::Util
8
7
 
9
8
  attr_reader :table_name
10
9
 
11
- def initialize(manager, table_name)
12
- @manager = manager
10
+ def initialize(table_name)
13
11
  @table_name = table_name
14
-
15
- @manager.async.poller_ready(@table_name, self)
16
12
  end
17
13
 
18
14
  def poll
@@ -25,12 +21,10 @@ module Shoryuken
25
21
  while item = next_item
26
22
  id = item.attributes['id']
27
23
  logger.info "Found message #{id} from '#{@table_name}'"
28
- defer do
29
- if sent_msg = process_item(item)
30
- logger.debug { "Enqueued message #{id} from '#{@table_name}' as #{sent_msg.id}" }
31
- else
32
- logger.debug { "Skipping already queued message #{id} from '#{@table_name}'" }
33
- end
24
+ if sent_msg = process_item(item)
25
+ logger.debug { "Enqueued message #{id} from '#{@table_name}' as #{sent_msg.id}" }
26
+ else
27
+ logger.debug { "Skipping already queued message #{id} from '#{@table_name}'" }
34
28
  end
35
29
  end
36
30
 
@@ -39,8 +33,6 @@ module Shoryuken
39
33
  logger.error "Error fetching message: #{ex}"
40
34
  logger.error ex.backtrace.first
41
35
  end
42
-
43
- @manager.async.poller_done(@table_name, self)
44
36
  end
45
37
  end
46
38
 
@@ -1,5 +1,5 @@
1
1
  module Shoryuken
2
2
  module Later
3
- VERSION = '0.0.5.4'
3
+ VERSION = '0.0.6'
4
4
  end
5
- end
5
+ end
@@ -28,6 +28,6 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency "pry-byebug"
29
29
 
30
30
  spec.add_dependency "aws-sdk-v1"
31
- spec.add_dependency "celluloid", "~> 0.16.0"
31
+ spec.add_dependency "timers", "~> 4.0.1"
32
32
  spec.add_dependency "shoryuken", "~> 0.0.5"
33
33
  end
@@ -1,9 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'shoryuken/later/poller'
3
- require 'shoryuken/later/manager'
4
3
 
5
4
  describe Shoryuken::Later::Poller do
6
- let(:manager) { double Shoryuken::Later::Manager, poller_ready: nil, poller_done: nil }
7
5
  let(:ddb_table) { double 'DynamoDb Table' }
8
6
  let(:ddb_items) { double 'Table Items' }
9
7
  let(:table) { 'shoryuken_later' }
@@ -17,38 +15,26 @@ describe Shoryuken::Later::Poller do
17
15
  end
18
16
 
19
17
  before do
20
- allow(manager).to receive(:async).and_return(manager)
21
18
  allow(Shoryuken::Later::Client).to receive(:tables).with(table).and_return(ddb_table)
22
19
  end
23
20
 
24
21
  subject do
25
- described_class.new(manager, table)
22
+ described_class.new(table)
26
23
  end
27
24
 
28
- describe '#initialize' do
29
- it 'informs the manager that the poller is ready' do
30
- expect(manager).to receive(:poller_ready).once
31
-
32
- subject.inspect
33
- subject.inspect
34
- end
35
- end
36
-
37
25
  describe '#poll' do
38
26
  it 'pulls items from #next_item, and processes with #process_item' do
39
27
  items = [ddb_item]
40
28
  expect_any_instance_of(described_class).to receive(:next_item).twice { items.pop }
41
29
  expect_any_instance_of(described_class).to receive(:process_item).once.with(ddb_item)
42
- expect(manager).to receive(:poller_done).once
43
30
 
44
31
  subject.poll
45
32
  end
46
33
 
47
- it 'informs the manager after polling is done' do
34
+ it 'does not call #process_item when there are no items' do
48
35
  items = []
49
36
  expect_any_instance_of(described_class).to receive(:next_item).once { items.pop }
50
37
  expect_any_instance_of(described_class).not_to receive(:process_item)
51
- expect(manager).to receive(:poller_done).once
52
38
 
53
39
  subject.poll
54
40
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'bundler/setup'
2
2
  Bundler.setup
3
3
 
4
- require 'celluloid'
5
4
  require 'shoryuken-later'
6
5
  require 'json'
7
6
 
@@ -16,7 +15,6 @@ if File.exists? options_file
16
15
  end
17
16
 
18
17
  Shoryuken.logger.level = Logger::UNKNOWN
19
- Celluloid.logger.level = Logger::UNKNOWN
20
18
 
21
19
  # For Ruby 1.9
22
20
  module Kernel
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shoryuken-later
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5.4
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Khoobyar
@@ -87,19 +87,19 @@ dependencies:
87
87
  - !ruby/object:Gem::Version
88
88
  version: '0'
89
89
  - !ruby/object:Gem::Dependency
90
- name: celluloid
90
+ name: timers
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - ~>
94
94
  - !ruby/object:Gem::Version
95
- version: 0.16.0
95
+ version: 4.0.1
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - ~>
101
101
  - !ruby/object:Gem::Version
102
- version: 0.16.0
102
+ version: 4.0.1
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: shoryuken
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -134,8 +134,6 @@ files:
134
134
  - lib/shoryuken/later/active_job_adapter.rb
135
135
  - lib/shoryuken/later/cli.rb
136
136
  - lib/shoryuken/later/client.rb
137
- - lib/shoryuken/later/launcher.rb
138
- - lib/shoryuken/later/manager.rb
139
137
  - lib/shoryuken/later/poller.rb
140
138
  - lib/shoryuken/later/version.rb
141
139
  - lib/shoryuken/later/worker.rb
@@ -1,44 +0,0 @@
1
- # All of this has been "borrowed" from Shoryuken.
2
-
3
- # @see Shoryuken::Launcher
4
- module Shoryuken
5
- module Later
6
- class Launcher
7
- include Celluloid
8
- include Shoryuken::Util
9
-
10
- trap_exit :actor_died
11
-
12
- attr_accessor :manager
13
-
14
- def initialize
15
- @condvar = Celluloid::Condition.new
16
- @manager = Shoryuken::Later::Manager.new_link(@condvar)
17
-
18
- @done = false
19
- end
20
-
21
- def stop(options = {})
22
- watchdog('Later::Launcher#stop') do
23
- @done = true
24
-
25
- manager.async.stop(shutdown: !!options[:shutdown], timeout: Shoryuken::Later.options[:timeout])
26
- @condvar.wait
27
- manager.terminate
28
- end
29
- end
30
-
31
- def run
32
- watchdog('Later::Launcher#run') do
33
- manager.async.start
34
- end
35
- end
36
-
37
- def actor_died(actor, reason)
38
- return if @done
39
- logger.warn 'Shoryuken::Later died due to the following error, cannot recover, process exiting'
40
- exit 1
41
- end
42
- end
43
- end
44
- end
@@ -1,139 +0,0 @@
1
- # Most of this has been "borrowed" from Shoryuken, but then repurposed for periodic polling.
2
-
3
- # @see Shoryuken::Manager
4
- require 'set'
5
- require 'shoryuken/later/poller'
6
-
7
- module Shoryuken
8
- module Later
9
- class Manager
10
- include Celluloid
11
- include Shoryuken::Util
12
-
13
- def initialize(condvar)
14
- @tables = Shoryuken::Later.tables.dup.uniq
15
- @finished = condvar
16
-
17
- @done = false
18
-
19
- @idle = Set.new([])
20
- @busy = Set.new([])
21
- @timers = {}
22
-
23
- @tables.each{|table| Poller.supervise_as :"poller-#{table}", current_actor, table }
24
- end
25
-
26
- def start
27
- logger.info 'Starting'
28
-
29
- # Start a poller for every table being polled.
30
- @tables.each do |table|
31
- dispatch table
32
-
33
- # Save the timer so it can be cancelled at shutdown.
34
- @timers[table] = every(Shoryuken::Later.poll_delay) { dispatch table }
35
- end
36
- end
37
-
38
- def stop(options = {})
39
- watchdog('Later::Manager#stop died') do
40
- @done = true
41
-
42
- @timers.each_value{|timer| timer.cancel if timer }
43
- @timers.clear
44
-
45
- logger.info { "Shutting down #{@idle.size} idle poller(s)" }
46
-
47
- @idle.each do |name|
48
- poller = Actor[name] and poller.alive? and poller.terminate
49
- end
50
- @idle.clear
51
-
52
- if @busy.empty?
53
- return after(0) { @finished.signal }
54
- end
55
-
56
- if options[:shutdown]
57
- hard_shutdown_in(options[:timeout])
58
- else
59
- soft_shutdown(options[:timeout])
60
- end
61
- end
62
- end
63
-
64
- def poller_done(table, poller)
65
- watchdog('Later::Manager#poller_done died') do
66
- logger.debug { "Poller done for '#{table}'" }
67
-
68
- name = :"poller-#{table}"
69
- @busy.delete name
70
-
71
- if stopped?
72
- poller.terminate if poller.alive?
73
- else
74
- @idle << name
75
- end
76
- end
77
- end
78
-
79
- def poller_ready(table, poller)
80
- watchdog('Later::Manager#poller_ready died') do
81
- logger.debug { "Poller for '#{table}' ready" }
82
-
83
- name = :"poller-#{table}"
84
- @busy.delete name
85
- @idle << name
86
- end
87
- end
88
-
89
- def stopped?
90
- @done
91
- end
92
-
93
- private
94
-
95
- def dispatch(table)
96
- name = :"poller-#{table}"
97
-
98
- # Only start polling if the poller is idle.
99
- if ! stopped? && @idle.include?(name)
100
- @idle.delete(name)
101
- @busy << name
102
-
103
- Actor[name].async.poll
104
- end
105
- end
106
-
107
- def soft_shutdown(delay)
108
- logger.info { "Waiting for #{@busy.size} busy pollers" }
109
-
110
- if @busy.size > 0
111
- after(delay) { soft_shutdown(delay) }
112
- else
113
- @finished.signal
114
- end
115
- end
116
-
117
- def hard_shutdown_in(delay)
118
- logger.info { "Waiting for #{@busy.size} busy pollers" }
119
- logger.info { "Pausing up to #{delay} seconds to allow pollers to finish..." }
120
-
121
- after(delay) do
122
- watchdog("Later::Manager#hard_shutdown_in died") do
123
- if @busy.size > 0
124
- logger.info { "Hard shutting down #{@busy.size} busy pollers" }
125
-
126
- @busy.each do |busy|
127
- if poller = Actor[busy]
128
- t = poller.bare_object.actual_work_thread
129
- t.raise Shutdown if poller.alive?
130
- end
131
- end
132
- end
133
- @finished.signal
134
- end
135
- end
136
- end
137
- end
138
- end
139
- end