shoryuken-later 0.0.5.4 → 0.0.6

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: 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