shoryuken-later 0.0.2 → 0.0.3
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 +8 -8
- data/README.md +106 -21
- data/Rakefile +0 -0
- data/lib/shoryuken/later/active_job_adapter.rb +0 -0
- data/lib/shoryuken/later/cli.rb +47 -52
- data/lib/shoryuken/later/client.rb +0 -0
- data/lib/shoryuken/later/poller.rb +5 -13
- data/lib/shoryuken/later/version.rb +1 -1
- data/lib/shoryuken/later/worker.rb +0 -0
- data/shoryuken-later.gemspec +3 -3
- data/spec/shoryuken/later/client_spec.rb +0 -0
- data/spec/shoryuken/later/poller_spec.rb +2 -16
- data/spec/shoryuken/worker_spec.rb +0 -0
- data/spec/spec_helper.rb +0 -2
- metadata +8 -10
- data/lib/shoryuken/later/launcher.rb +0 -42
- data/lib/shoryuken/later/manager.rb +0 -138
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZmRmMzRlZjhlM2I4YTM3NjhjNDUxOTQxYzYwZTE1ZjZiNGNiMWQwNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTQwODFkZDI4YmE4NGM2MzZiZjFkM2NmNTViZTk4OWQ3NGI2NzVhYQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NjYxMDExNjQzYjhhNTJmZWE3ZmZmZWMxYjRmN2IwYjU1OTU0Nzg4NTIyOGQx
|
10
|
+
YzM0NzUzNjZjYzAzOTBjNDZiZGEzYTk3ZDU0MjdmM2ZlNmI0OTg5ZWQ4YjM2
|
11
|
+
NWU1Y2U0NDZmMTZkY2QwYjE5MTJlYzJjMmI1MzA5NzVkNGE2YTE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MzRiYjI0NDUxMGExNzVmMjA3ZDRlNDlkM2E0NzgzZTc1ZGM5YWE2YzY0OGQy
|
14
|
+
Y2Q0N2QwZjEwMzM2YmUxYzMxYjBkYzUxOWQ0ZjFkNjMwOTNhNjM2MzkxMzdi
|
15
|
+
ZWRiOGRlYjk1MTIzM2IzYjU1ZWJkOWJlNWI2OWQxY2JlMWFiNzg=
|
data/README.md
CHANGED
@@ -1,26 +1,15 @@
|
|
1
1
|
# shoryuken-later
|
2
2
|
|
3
3
|
A scheduling plugin for [Shoryuken](https://github.com/phstc/shoryuken) that uses [Dynamo DB](https://aws.amazon.com/dynamodb/)
|
4
|
-
to
|
4
|
+
to delay messages arbitrarily far into the future.
|
5
5
|
|
6
6
|
## Features
|
7
7
|
|
8
|
-
###
|
9
|
-
|
10
|
-
A new method named `perform_later` is added to `Shoryuken::Worker` allowing messages to be delayed arbitrarily far into the future. If the delay is 15 minutes or less, then the message is enqueued into the specified SQS `:queue` as usual. Otherwise, the message is inserted into the specified DynamoDB `:schedule_table`.
|
11
|
-
|
12
|
-
```ruby
|
13
|
-
require 'shoryuken-later'
|
8
|
+
### Supports distributed architectures
|
14
9
|
|
15
|
-
|
16
|
-
include Shoryuken::Worker
|
17
|
-
|
18
|
-
shoryuken_options queue: 'default', schedule_table: 'default_schedule'
|
19
|
-
end
|
10
|
+
An SQS message is *only* queued if a _conditional_ delete of the DDB item is successful. This eliminates any potential race condition, so if more than one `shoryuken-later` process is polling the same schedule table then no redundant SQS messages will be queued.
|
20
11
|
|
21
|
-
|
22
|
-
MyWorker.perform_later(Time.now + 30 * 60, 'Foobar')
|
23
|
-
```
|
12
|
+
NOTE: You shouldn't really _need_ to run more than one process, but if you do it will be safe.
|
24
13
|
|
25
14
|
### One or more schedule tables
|
26
15
|
|
@@ -38,21 +27,19 @@ later:
|
|
38
27
|
You can use the same configuration file for both `Shoryuken` and `Shoryuken::Later`, because the new configuration options are namespaced.
|
39
28
|
|
40
29
|
```yaml
|
41
|
-
#
|
30
|
+
# These keys are used by both Shoryuken and Shoryuken::Later
|
42
31
|
aws:
|
43
32
|
access_key_id: ... # or <%= ENV['AWS_ACCESS_KEY_ID'] %>
|
44
33
|
secret_access_key: ... # or <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
|
45
34
|
region: us-east-1 # or <%= ENV['AWS_REGION'] %>
|
35
|
+
logfile: some/path/to/file.log
|
46
36
|
|
47
37
|
# This key is only used by Shoryuken::Later
|
48
38
|
later:
|
49
39
|
delay: 5 * 60 # How frequently to poll the schedule table, in seconds.
|
40
|
+
pidfile: some/path/to/file.pid
|
50
41
|
tables:
|
51
42
|
- table1
|
52
|
-
|
53
|
-
# These keys are used by both Shoryuken and Shoryuken::Later
|
54
|
-
logfile: some/path/to/file.log
|
55
|
-
pidfile: some/path/to/file.pid
|
56
43
|
|
57
44
|
# These keys are only used by Shoryuken
|
58
45
|
concurrency: 3
|
@@ -60,4 +47,102 @@ delay: 0
|
|
60
47
|
queues:
|
61
48
|
- [queue1, 1]
|
62
49
|
- [queue2, 2]
|
63
|
-
```
|
50
|
+
```
|
51
|
+
|
52
|
+
## Usage
|
53
|
+
|
54
|
+
### Starting the schedule poller
|
55
|
+
|
56
|
+
Start the `shoryuken-later` schedule poller with a command like:
|
57
|
+
|
58
|
+
```shell
|
59
|
+
bundle exec shoryuken-later --config shoryuken.yml
|
60
|
+
```
|
61
|
+
|
62
|
+
Run it as a daemon inside of your Rails app with a command like:
|
63
|
+
|
64
|
+
```shell
|
65
|
+
bundle exec shoryuken-later --config shoryuken.yml --rails --daemon
|
66
|
+
```
|
67
|
+
|
68
|
+
[Command-line options](https://github.com/joekhoobyar/shoryuken-later/wiki/Command-line-options)
|
69
|
+
|
70
|
+
|
71
|
+
### Integration with ActiveJob
|
72
|
+
|
73
|
+
A custom ActiveJob adapter can used to support delaying messages arbitrarily far into the future.
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
# config/application.rb
|
77
|
+
config.active_job.queue_adapter = :shoryuken_later
|
78
|
+
```
|
79
|
+
|
80
|
+
When you use the `:shoryuken_later` queue adapter, jobs to be performed farther than 15 minutes into the future (by setting the `wait` or `wait_until` ActiveJob options), will be inserted into the *default* schedule table. You can set the default schedule table in an initializer.
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# config/initializers/shoryuken_later.rb
|
84
|
+
Shoryuken::Later.default_table = "#{Rails.env}_myapp_later"
|
85
|
+
```
|
86
|
+
|
87
|
+
|
88
|
+
### Integration with Shoryuken::Worker
|
89
|
+
|
90
|
+
A new method named `perform_later` is added to `Shoryuken::Worker` allowing messages to be delayed arbitrarily far into the future. If the delay is 15 minutes or less, then the message is enqueued into the specified SQS `:queue` as usual. Otherwise, the message is inserted into the specified DynamoDB `:schedule_table`.
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
require 'shoryuken-later'
|
94
|
+
|
95
|
+
class MyWorker
|
96
|
+
include Shoryuken::Worker
|
97
|
+
|
98
|
+
shoryuken_options queue: 'default', schedule_table: 'default_schedule'
|
99
|
+
end
|
100
|
+
|
101
|
+
# Schedules a message to be processed 30 minutes from now.
|
102
|
+
MyWorker.perform_later(Time.now + 30 * 60, 'Foobar')
|
103
|
+
```
|
104
|
+
|
105
|
+
|
106
|
+
## Requirements
|
107
|
+
|
108
|
+
Ruby 1.9 or greater.
|
109
|
+
|
110
|
+
## Installation
|
111
|
+
|
112
|
+
Add this line to your application's Gemfile:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
gem 'shoryuken-later'
|
116
|
+
```
|
117
|
+
|
118
|
+
Or to get the latest updates:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
gem 'shoryuken-later', github: 'joekhoobyar/shoryuken-later', branch: 'master'
|
122
|
+
```
|
123
|
+
|
124
|
+
And then execute:
|
125
|
+
|
126
|
+
$ bundle
|
127
|
+
|
128
|
+
Or install it yourself as:
|
129
|
+
|
130
|
+
$ gem install shoryuken-later
|
131
|
+
|
132
|
+
## Documentation
|
133
|
+
|
134
|
+
Learn about using Shoryuken::Later at the [Shoryuken::Later Wiki](https://github.com/joekhoobyar/shoryuken-later/wiki).
|
135
|
+
|
136
|
+
Learn about using Shoryuken at the [Shoryuken Wiki](https://github.com/phstc/shoryuken/wiki).
|
137
|
+
|
138
|
+
## Credits
|
139
|
+
|
140
|
+
[Pablo Cantero](https://github.com/phstc), creator of [Shoryuken](https://github.com/phstc/shoryuken), and [everybody who contributed to it](https://github.com/phstc/shoryuken/graphs/contributors). I borrowed a lot of code from Shoryuken itself as a shortcut to making this gem.
|
141
|
+
|
142
|
+
## Contributing
|
143
|
+
|
144
|
+
1. Fork it ( https://github.com/joekhoobyar/shoryuken-later/fork )
|
145
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
146
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
147
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
148
|
+
5. Create a new Pull Request
|
data/Rakefile
CHANGED
File without changes
|
File without changes
|
data/lib/shoryuken/later/cli.rb
CHANGED
@@ -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,12 +15,10 @@ 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
|
|
22
|
-
%w[INT TERM USR1 USR2
|
21
|
+
%w[INT TERM USR1 USR2].each do |sig|
|
23
22
|
trap sig do
|
24
23
|
self_write.puts(sig)
|
25
24
|
end
|
@@ -34,38 +33,49 @@ module Shoryuken
|
|
34
33
|
validate!
|
35
34
|
daemonize
|
36
35
|
write_pid
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
36
|
+
|
37
|
+
Shoryuken::Logging.with_context '[later]' do
|
38
|
+
logger.info 'Starting'
|
39
|
+
|
40
|
+
# Initialize the timers and poller.
|
41
|
+
@timers = Timers.new
|
42
|
+
require 'shoryuken/later/poller'
|
43
|
+
@pollers = Shoryuken::Later.tables.map{|tbl| Poller.new(tbl) }
|
44
|
+
|
45
|
+
begin
|
46
|
+
# Poll for items on startup, and every :poll_delay
|
47
|
+
poll_tables
|
48
|
+
@timers.every(Shoryuken::Later.poll_delay){ poll_tables }
|
49
|
+
|
50
|
+
# Loop watching for signals and firing off of timers
|
51
|
+
while @timers
|
52
|
+
interval = @timers.wait_interval
|
53
|
+
readable, writable = IO.select([self_read], nil, nil, interval)
|
54
|
+
if readable
|
55
|
+
handle_signal readable.first.gets.strip
|
56
|
+
else
|
57
|
+
@timers.fire
|
58
|
+
end
|
59
|
+
end
|
60
|
+
rescue Interrupt
|
61
|
+
@timers.cancel
|
62
|
+
exit 0
|
48
63
|
end
|
49
|
-
rescue Interrupt
|
50
|
-
launcher.stop(shutdown: true)
|
51
|
-
exit 0
|
52
64
|
end
|
53
65
|
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
def poll_tables
|
70
|
+
logger.debug "Polling schedule tables"
|
71
|
+
@pollers.each do |poller|
|
72
|
+
poller.poll
|
73
|
+
end
|
74
|
+
logger.debug "Polling done"
|
75
|
+
end
|
54
76
|
|
55
77
|
private
|
56
78
|
|
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
79
|
def load_rails
|
70
80
|
# Adapted from: https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/cli.rb
|
71
81
|
|
@@ -79,6 +89,7 @@ module Shoryuken
|
|
79
89
|
::Rails::Application.initializer "shoryuken-later.eager_load" do
|
80
90
|
::Rails.application.config.eager_load = true
|
81
91
|
end
|
92
|
+
require 'shoryuken/later/active_job_adapter' if defined?(::ActiveJob)
|
82
93
|
require File.expand_path("config/environment.rb")
|
83
94
|
end
|
84
95
|
|
@@ -117,7 +128,7 @@ module Shoryuken
|
|
117
128
|
end
|
118
129
|
|
119
130
|
def write_pid
|
120
|
-
if path = Shoryuken::Later.options[:pidfile]
|
131
|
+
if path = Shoryuken::Later.options[:later][:pidfile]
|
121
132
|
File.open(path, 'w') do |f|
|
122
133
|
f.puts Process.pid
|
123
134
|
end
|
@@ -125,7 +136,7 @@ module Shoryuken
|
|
125
136
|
end
|
126
137
|
|
127
138
|
def parse_options(argv)
|
128
|
-
opts = {}
|
139
|
+
opts = {later: {}}
|
129
140
|
|
130
141
|
@parser = OptionParser.new do |o|
|
131
142
|
o.on '-d', '--daemon', 'Daemonize process' do |arg|
|
@@ -153,7 +164,7 @@ module Shoryuken
|
|
153
164
|
end
|
154
165
|
|
155
166
|
o.on '-P', '--pidfile PATH', 'Path to pidfile' do |arg|
|
156
|
-
opts[:pidfile] = arg
|
167
|
+
opts[:later][:pidfile] = arg
|
157
168
|
end
|
158
169
|
|
159
170
|
o.on '-v', '--verbose', 'Print more verbose output' do |arg|
|
@@ -181,28 +192,10 @@ module Shoryuken
|
|
181
192
|
case sig
|
182
193
|
when 'USR1'
|
183
194
|
logger.info "Received USR1, will soft shutdown down"
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
exit 0
|
188
|
-
when 'TTIN'
|
189
|
-
Thread.list.each do |thread|
|
190
|
-
logger.info "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
191
|
-
if thread.backtrace
|
192
|
-
logger.info thread.backtrace.join("\n")
|
193
|
-
else
|
194
|
-
logger.info "<no backtrace available>"
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
idle = launcher.manager.instance_variable_get(:@idle).size
|
199
|
-
busy = launcher.manager.instance_variable_get(:@busy).size
|
200
|
-
tables = launcher.manager.instance_variable_get(:@tables)
|
201
|
-
|
202
|
-
logger.info "Idle: #{idle}, Busy: #{busy}, Polled Tables: #{tables.join(', ')}"
|
195
|
+
@timers.cancel
|
196
|
+
@timers = nil
|
203
197
|
else
|
204
198
|
logger.info "Received #{sig}, will shutdown down"
|
205
|
-
|
206
199
|
raise Interrupt
|
207
200
|
end
|
208
201
|
end
|
@@ -215,8 +208,10 @@ module Shoryuken
|
|
215
208
|
|
216
209
|
config = options[:config_file] ? parse_config(options[:config_file]).deep_symbolize_keys : {}
|
217
210
|
|
211
|
+
Shoryuken::Later.options[:later].merge!(config.delete(:later) || {})
|
218
212
|
Shoryuken::Later.options.merge!(config)
|
219
213
|
|
214
|
+
Shoryuken::Later.options[:later].merge!(options.delete(:later) || {})
|
220
215
|
Shoryuken::Later.options.merge!(options)
|
221
216
|
|
222
217
|
# Tables from command line options take precedence...
|
File without changes
|
@@ -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(
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
|
File without changes
|
data/shoryuken-later.gemspec
CHANGED
@@ -20,13 +20,13 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.required_ruby_version = '>= 1.9.
|
23
|
+
spec.required_ruby_version = '>= 1.9.2'
|
24
24
|
|
25
25
|
spec.add_development_dependency "bundler", '>= 1.3.5'
|
26
26
|
spec.add_development_dependency "rake", '~> 10.0'
|
27
27
|
spec.add_development_dependency "rspec", '~> 3.0', '< 3.1'
|
28
28
|
|
29
29
|
spec.add_dependency "aws-sdk-v1"
|
30
|
-
spec.add_dependency "
|
31
|
-
spec.add_dependency "shoryuken", "
|
30
|
+
spec.add_dependency "timers", "~> 1.1.0"
|
31
|
+
spec.add_dependency "shoryuken", "= 0.0.4"
|
32
32
|
end
|
File without changes
|
@@ -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(
|
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 '
|
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
|
File without changes
|
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,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shoryuken-later
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Khoobyar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -73,31 +73,31 @@ dependencies:
|
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
|
-
name:
|
76
|
+
name: timers
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - ~>
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version:
|
81
|
+
version: 1.1.0
|
82
82
|
type: :runtime
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - ~>
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version:
|
88
|
+
version: 1.1.0
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
90
|
name: shoryuken
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
|
-
- -
|
93
|
+
- - '='
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: 0.0.4
|
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
102
|
version: 0.0.4
|
103
103
|
description: ! "\n This gem provides a scheduling plugin (using Dynamo DB) for
|
@@ -120,8 +120,6 @@ files:
|
|
120
120
|
- lib/shoryuken/later/active_job_adapter.rb
|
121
121
|
- lib/shoryuken/later/cli.rb
|
122
122
|
- lib/shoryuken/later/client.rb
|
123
|
-
- lib/shoryuken/later/launcher.rb
|
124
|
-
- lib/shoryuken/later/manager.rb
|
125
123
|
- lib/shoryuken/later/poller.rb
|
126
124
|
- lib/shoryuken/later/version.rb
|
127
125
|
- lib/shoryuken/later/worker.rb
|
@@ -142,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
140
|
requirements:
|
143
141
|
- - ! '>='
|
144
142
|
- !ruby/object:Gem::Version
|
145
|
-
version: 1.9.
|
143
|
+
version: 1.9.2
|
146
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
145
|
requirements:
|
148
146
|
- - ! '>='
|
@@ -1,42 +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
|
-
@manager = Shoryuken::Later::Manager.new_link
|
16
|
-
|
17
|
-
@done = false
|
18
|
-
end
|
19
|
-
|
20
|
-
def stop(options = {})
|
21
|
-
watchdog('Later::Launcher#stop') do
|
22
|
-
@done = true
|
23
|
-
|
24
|
-
manager.async.stop(shutdown: !!options[:shutdown], timeout: Shoryuken::Later.options[:timeout])
|
25
|
-
manager.wait(:shutdown)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def run
|
30
|
-
watchdog('Later::Launcher#run') do
|
31
|
-
manager.async.start
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def actor_died(actor, reason)
|
36
|
-
return if @done
|
37
|
-
logger.warn 'Shoryuken::Later died due to the following error, cannot recover, process exiting'
|
38
|
-
exit 1
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,138 +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
|
14
|
-
@tables = Shoryuken::Later.tables.dup.uniq
|
15
|
-
|
16
|
-
@done = false
|
17
|
-
|
18
|
-
@idle = Set.new([])
|
19
|
-
@busy = Set.new([])
|
20
|
-
@timers = {}
|
21
|
-
|
22
|
-
@tables.each{|table| Poller.supervise_as :"poller-#{table}", current_actor, table }
|
23
|
-
end
|
24
|
-
|
25
|
-
def start
|
26
|
-
logger.info 'Starting'
|
27
|
-
|
28
|
-
# Start a poller for every table being polled.
|
29
|
-
@tables.each do |table|
|
30
|
-
dispatch table
|
31
|
-
|
32
|
-
# Save the timer so it can be cancelled at shutdown.
|
33
|
-
@timers[table] = every(Shoryuken::Later.poll_delay) { dispatch table }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def stop(options = {})
|
38
|
-
watchdog('Later::Manager#stop died') do
|
39
|
-
@done = true
|
40
|
-
|
41
|
-
@timers.each_value{|timer| timer.cancel if timer }
|
42
|
-
@timers.clear
|
43
|
-
|
44
|
-
logger.info { "Shutting down #{@idle.size} idle poller(s)" }
|
45
|
-
|
46
|
-
@idle.each do |name|
|
47
|
-
poller = Actor[name] and poller.alive? and poller.terminate
|
48
|
-
end
|
49
|
-
@idle.clear
|
50
|
-
|
51
|
-
if @busy.empty?
|
52
|
-
return after(0) { signal(:shutdown) }
|
53
|
-
end
|
54
|
-
|
55
|
-
if options[:shutdown]
|
56
|
-
hard_shutdown_in(options[:timeout])
|
57
|
-
else
|
58
|
-
soft_shutdown(options[:timeout])
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def poller_done(table, poller)
|
64
|
-
watchdog('Later::Manager#poller_done died') do
|
65
|
-
logger.debug { "Poller done for '#{table}'" }
|
66
|
-
|
67
|
-
name = :"poller-#{table}"
|
68
|
-
@busy.delete name
|
69
|
-
|
70
|
-
if stopped?
|
71
|
-
poller.terminate if poller.alive?
|
72
|
-
else
|
73
|
-
@idle << name
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def poller_ready(table, poller)
|
79
|
-
watchdog('Later::Manager#poller_ready died') do
|
80
|
-
logger.debug { "Poller for '#{table}' ready" }
|
81
|
-
|
82
|
-
name = :"poller-#{table}"
|
83
|
-
@busy.delete name
|
84
|
-
@idle << name
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def stopped?
|
89
|
-
@done
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
def dispatch(table)
|
95
|
-
name = :"poller-#{table}"
|
96
|
-
|
97
|
-
# Only start polling if the poller is idle.
|
98
|
-
if ! stopped? && @idle.include?(name)
|
99
|
-
@idle.delete(name)
|
100
|
-
@busy << name
|
101
|
-
|
102
|
-
Actor[name].async.poll
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def soft_shutdown(delay)
|
107
|
-
logger.info { "Waiting for #{@busy.size} busy pollers" }
|
108
|
-
|
109
|
-
if @busy.size > 0
|
110
|
-
after(delay) { soft_shutdown(delay) }
|
111
|
-
else
|
112
|
-
after(0) { signal(:shutdown) }
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def hard_shutdown_in(delay)
|
117
|
-
logger.info { "Waiting for #{@busy.size} busy pollers" }
|
118
|
-
logger.info { "Pausing up to #{delay} seconds to allow pollers to finish..." }
|
119
|
-
|
120
|
-
after(delay) do
|
121
|
-
watchdog("Later::Manager#hard_shutdown_in died") do
|
122
|
-
if @busy.size > 0
|
123
|
-
logger.info { "Hard shutting down #{@busy.size} busy pollers" }
|
124
|
-
|
125
|
-
@busy.each do |busy|
|
126
|
-
if poller = Actor[busy]
|
127
|
-
t = poller.bare_object.actual_work_thread
|
128
|
-
t.raise Shutdown if poller.alive?
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
after(0) { signal(:shutdown) }
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|