tread_mill 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +28 -0
- data/README.md +152 -0
- data/Rakefile +28 -0
- data/lib/tasks/tread_mill_tasks.rake +8 -0
- data/lib/tread_mill.rb +68 -0
- data/lib/tread_mill/fork_callbacks.rb +20 -0
- data/lib/tread_mill/queue_listener.rb +23 -0
- data/lib/tread_mill/railtie.rb +19 -0
- data/lib/tread_mill/version.rb +3 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +24 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +82 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/assets.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +2 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +10 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/queue_listener_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- data/test/tread_mill_test.rb +7 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f5cc9f12b5f080934e1e27c98fdd6c8bd1d49a7a
|
4
|
+
data.tar.gz: 860247bf4d4a9fc23508e41b5b2798c3c7ded808
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c3777805116b0a99afe44bf77be919099c3c7a075001e1be7e43ffb08557163b619c4c6ed80671abe575e0de80f38fe145cd3ef123cd10dbc56ef45c573d0e26
|
7
|
+
data.tar.gz: 63d5bb6e9f193a1003eab217155fc2ad7caa8f3415181da9a98f1718b79f6c30acdd8e249679408338a11bc17e9d25081756cae692e986ce3ea723ddb56a82e1
|
data/LICENSE
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Copyright (c) 2014, Protobit
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
* Neither the name of the {organization} nor the names of its
|
15
|
+
contributors may be used to endorse or promote products derived from
|
16
|
+
this software without specific prior written permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
22
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
|
data/README.md
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# TreadMill
|
2
|
+
|
3
|
+
TreadMill Rails plugin for background workers. This gem is designed to integrate into an existing Rails application and provide immediate RabbitMQ integration using the Sneakers worker gem and Rails 4.2.0.beta1 ActiveJob.
|
4
|
+
|
5
|
+
## Notes
|
6
|
+
|
7
|
+
Tags:
|
8
|
+
|
9
|
+
* [0.0.1](/Protobit/tread_mill/wiki/0.0.1) tag for Rails 4.1
|
10
|
+
* [0.0.2](/Protobit/tread_mill/wiki/0.0.1) tag for Rails 4.2.0.beta1
|
11
|
+
* HEAD or 0.0.3 tag for Rails 4.2 stable
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your applications's Gemfile:
|
16
|
+
|
17
|
+
```
|
18
|
+
gem 'tread_mill'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
```
|
24
|
+
bundle install
|
25
|
+
```
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
### Options
|
30
|
+
|
31
|
+
```RUBY
|
32
|
+
module MyApp
|
33
|
+
class Application < Rails::Application
|
34
|
+
# Queues you wish to listen on.
|
35
|
+
config.active_job.queue_name_delimiter = '.'
|
36
|
+
config.active_job.queue_adapter = :sneakers
|
37
|
+
config.active_job.queue_base_name = 'amqp.myapplication'
|
38
|
+
|
39
|
+
# configure queues: amqp.myapplication.my_queue and amqp.myapplication.my_second_queue
|
40
|
+
config.tread_mill.queues = %w(my_queue my_second_queue)
|
41
|
+
|
42
|
+
# Configure 'ActionMailer#deliver_later': amqp.myapplication.mailers
|
43
|
+
config.tread_mill.queues << 'mailers'
|
44
|
+
|
45
|
+
# Optional: Probably best set in your sneakers configuration.
|
46
|
+
# config.tread_mill.workers = # of workers
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
### Running your ActiveJob based workers.
|
53
|
+
|
54
|
+
```
|
55
|
+
rake tread_mill:run
|
56
|
+
```
|
57
|
+
|
58
|
+
**That's it.**
|
59
|
+
|
60
|
+
### Example Upstart:
|
61
|
+
|
62
|
+
As suggested by jondot, the Sneakers maintainer, daemons used to run jobs with
|
63
|
+
Sneakers, and thusly TreadMill, should be done so using Upstart (or whatever
|
64
|
+
flavor other of daemon management subsystems your chosen OS uses). Sneakers
|
65
|
+
no longer supports the ability to daemonize.
|
66
|
+
|
67
|
+
The following a sample upstart config file to get you started:
|
68
|
+
|
69
|
+
```
|
70
|
+
description 'Application Tread Mill Server'
|
71
|
+
|
72
|
+
env ENVIRONMENT_VAR='VALUE'
|
73
|
+
|
74
|
+
setuid deploy
|
75
|
+
setgid www-data
|
76
|
+
|
77
|
+
chdir /srv/www/application/current
|
78
|
+
|
79
|
+
start on [2345]
|
80
|
+
stop on [!2345]
|
81
|
+
|
82
|
+
exec /usr/local/bin/ruby /usr/local/bin/bundle exec rake tread_mill:run
|
83
|
+
```
|
84
|
+
|
85
|
+
This file will go in `/etc/init` on Ubuntu systems. Should be named with the
|
86
|
+
service name followed by `.conf`: `application-treadmill.conf`.
|
87
|
+
|
88
|
+
Now to start/stop your service:
|
89
|
+
|
90
|
+
```BASH
|
91
|
+
root@nix:/root# start application-treadmill
|
92
|
+
application-treadmill start/running, process 27996
|
93
|
+
...
|
94
|
+
root@nix:/root# stop application-treadmill
|
95
|
+
application-treadmill stop/waiting
|
96
|
+
```
|
97
|
+
|
98
|
+
More information on Upstart can be found [here](http://upstart.ubuntu.com/cookbook/#console).
|
99
|
+
|
100
|
+
**NOTE: Upstart `restart` is not the command you are looking for *waves 2
|
101
|
+
fingers from left to right in front of you*. You must stop/start between
|
102
|
+
configuration changes for the changes to take effect.**
|
103
|
+
|
104
|
+
### Example workers:
|
105
|
+
|
106
|
+
Assuming you are using the ActiveJob::Base worker class:
|
107
|
+
|
108
|
+
```Ruby
|
109
|
+
# app/workers/my_worker.rb
|
110
|
+
|
111
|
+
# Assuming: config.active_job.queue_name_delimiter = '.'
|
112
|
+
|
113
|
+
class Workers::MyWorker < ActiveJob::Base
|
114
|
+
queue_as :my_queue # queue used will be 'amqp.myapplication.my_queue'
|
115
|
+
|
116
|
+
def perform(user)
|
117
|
+
user.do_work
|
118
|
+
end
|
119
|
+
|
120
|
+
class << self
|
121
|
+
def work_for(user)
|
122
|
+
self.enqueue(user)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
Then you are set to use your workers wherever you want:
|
129
|
+
|
130
|
+
```Ruby
|
131
|
+
# app/models/user.rb
|
132
|
+
|
133
|
+
class User
|
134
|
+
def work_later
|
135
|
+
Workers::MyWorker.work_for(self)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
### Support Versions
|
141
|
+
|
142
|
+
#### Rails 4.2.0
|
143
|
+
|
144
|
+
Should be working now. If you see any issues, feel free to submit a Pull Request.
|
145
|
+
|
146
|
+
#### Rails 4.2.0.beta1
|
147
|
+
|
148
|
+
TreadMill should work out of the box with a valid Sneakers configuration. For ActionMailer::DeliverLater integration, all you need to do is include a `:mailer` queue, which should be prefixed by your selected `queue_name_prefix` (`config.tread_mill.queues = %(amqp.myapplication.mailers)`).
|
149
|
+
|
150
|
+
#### Rails <=4.1
|
151
|
+
|
152
|
+
Due to a pretty large set of API changes between ActiveJob's github repository pre-merge and now, it doesn't make sense to support pre-4.2 ActiveJob, especially considering the Rails team has flatly rejected supporting pre-4.2. As a result, this gem as of version `0.0.2`, only supports `>= 4.2.0.beta1`.
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'TreadMill'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
Bundler::GemHelper.install_tasks
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
|
21
|
+
Rake::TestTask.new(:test) do |t|
|
22
|
+
t.libs << 'lib'
|
23
|
+
t.libs << 'test'
|
24
|
+
t.pattern = 'test/**/*_test.rb'
|
25
|
+
t.verbose = false
|
26
|
+
end
|
27
|
+
|
28
|
+
task default: :test
|
data/lib/tread_mill.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Load sneakers...
|
4
|
+
require 'sneakers'
|
5
|
+
require 'sneakers/runner'
|
6
|
+
|
7
|
+
require 'tread_mill/fork_callbacks'
|
8
|
+
require 'tread_mill/queue_listener'
|
9
|
+
|
10
|
+
module TreadMill
|
11
|
+
include ActiveSupport::Configurable
|
12
|
+
|
13
|
+
config_accessor :queues, :workers
|
14
|
+
|
15
|
+
# Check to see if we're properly configured to send messages.
|
16
|
+
# Unfortunately, sneakers/bunny doesn't have a real method check because
|
17
|
+
# the connections are setup at request time. This is really just a best
|
18
|
+
# guess.
|
19
|
+
def self.configured?
|
20
|
+
Sneakers.configured? &&
|
21
|
+
!Sneakers::Config[:amqp]
|
22
|
+
.match(/^amqps?:\/\/([^:]+(:[^@]+)?@)?[^:]+(:[0-9]+)?\/?$/).nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Process input queues to ensure QueueListener#for_queues gets the proper
|
26
|
+
# input.
|
27
|
+
def self.process_queues(queues)
|
28
|
+
case queues
|
29
|
+
when Array
|
30
|
+
queues.flatten
|
31
|
+
when String
|
32
|
+
queues.split(',')
|
33
|
+
else
|
34
|
+
fail ArgumentError, 'TreadMill#run_queues must be passed an Array of '\
|
35
|
+
'queues or comma separated list of queues.'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
mattr_accessor :runner
|
40
|
+
|
41
|
+
# Setup QueueListeners for each queue and run them in a Sneakers::Runner.
|
42
|
+
# Take the passed in queues first if provided, then use any application
|
43
|
+
# configured queues.
|
44
|
+
def self.run_queues(ques = nil, options = {})
|
45
|
+
ques = self.process_queues(ques) if ques
|
46
|
+
queue_listeners = QueueListener.for_queues(ques || queues)
|
47
|
+
|
48
|
+
sneakers_config = {
|
49
|
+
before_fork: ForkCallbacks.method(:before_fork),
|
50
|
+
after_fork: ForkCallbacks.method(:after_fork)
|
51
|
+
}
|
52
|
+
|
53
|
+
# Let these primarily reside in the sneakers config unless explicitly set.
|
54
|
+
sneakers_config[:workers] = workers if workers
|
55
|
+
|
56
|
+
Sneakers.configure(sneakers_config.merge(options))
|
57
|
+
|
58
|
+
self.runner = Sneakers::Runner.new(queue_listeners)
|
59
|
+
self.runner.run
|
60
|
+
end
|
61
|
+
|
62
|
+
# If a runner is running, stop it.
|
63
|
+
def self.stop_queues
|
64
|
+
self.runner.stop unless self.runner.nil?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
require 'tread_mill/railtie' if defined?(Rails)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TreadMill
|
4
|
+
# Encapsulate before and after fork collbacks.
|
5
|
+
|
6
|
+
module ForkCallbacks
|
7
|
+
def self.before_fork
|
8
|
+
# as there's no need for the master process to hold a connection
|
9
|
+
if defined?(ActiveRecord::Base)
|
10
|
+
ActiveRecord::Base.connection.disconnect!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.after_fork
|
15
|
+
if defined?(ActiveRecord::Base)
|
16
|
+
ActiveRecord::Base.establish_connection
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'active_job/queue_adapters/sneakers_adapter'
|
4
|
+
|
5
|
+
module TreadMill
|
6
|
+
# We want to subclass the JobWrapper to ensure the messages are deserialized
|
7
|
+
# properly.
|
8
|
+
class QueueListener < ActiveJob::QueueAdapters::SneakersAdapter::JobWrapper
|
9
|
+
include ActiveSupport::Rescuable
|
10
|
+
|
11
|
+
# Generate a worker for each queue specified.
|
12
|
+
def self.for_queues(*queues)
|
13
|
+
queues.flatten.map do |queue|
|
14
|
+
# Sneakers::Runner wants a worker class, not an instance.
|
15
|
+
# So, here we are creating anonymous classes and setting the queue
|
16
|
+
# accordingly.
|
17
|
+
Class.new(QueueListener) do
|
18
|
+
from_queue queue
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TreadMill
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
railtie_name :tread_mill
|
6
|
+
|
7
|
+
config.tread_mill = ActiveSupport::OrderedOptions.new
|
8
|
+
|
9
|
+
rake_tasks do
|
10
|
+
load "tasks/tread_mill_tasks.rake"
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer "tread_mill.set_configs" do |app|
|
14
|
+
options = app.config.tread_mill
|
15
|
+
options.queues ||= []
|
16
|
+
options.each { |k,v| TreadMill.send("#{k}=", v.flatten) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/test/dummy/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
11
|
+
* file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|