web_task_runner 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c5828a4e9a9b521c206ae34e2102f30ff0cfe5b9
4
+ data.tar.gz: ecec3fabb1fde45795da529adef6153adb9bc514
5
+ SHA512:
6
+ metadata.gz: 5b25a18f7e7f56786a4a13a617c4f70fd192db8f65be0a2638e0c40369998e7d0c1be8815ae8c962d8e39f298531ef66e21a58c901e9a40e67dc8131a4e62452
7
+ data.tar.gz: 3c2210c4ea5266cd889975bb4f5da9d200bd21abb9a88f8c1b111e19442489b2925ffc3add379d7acbf50cd1b0bbad7ee851cf82223f752227f0fe6c6bc8f0a9
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in web_task_runner.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # WebTaskRunner
2
+
3
+ Web wrapper to run a specific task with [Sidekiq](http://sidekiq.org/).
4
+ Provides HTTP API to start, stop, get status of the task running in background,
5
+ and is deployable to cloud platforms like Heroku.
6
+
7
+ A task is set of jobs for an specific purpose, like crawling a website, syncing
8
+ data... etc. For easy manageability, one task runner only provides running one
9
+ separate task.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'web_task_runner'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+
24
+ ## Requirements
25
+
26
+ Redis is required to run the background jobs. Make sure you have one, and set
27
+ the `REDIS_URL` environment variable to the Redis URL.
28
+
29
+ ## Getting Start
30
+
31
+ Create and `cd` into a new folder to place the task runner app. After adding
32
+ `gem 'web_task_runner'` into your project's `Gemfile`
33
+ (`echo "gem 'web_task_runner'" >> Gemfile`), run the `bundle` command to
34
+ install it, then proceed on the following to set it up:
35
+
36
+ ### Set the Environment Variables
37
+
38
+ The following environment variables should be configured for the task runner
39
+ app to run, you can set it using `$ export` or save them into a file called
40
+ `.env` right under the project folder.
41
+
42
+ - `REDIS_URL`: specify the Redis to connect to
43
+ - `API_KEY`: chose a secret key for accessing the web API
44
+
45
+ ### Create The App
46
+
47
+ Create an file, for instance, `./app.rb` (`touch app.rb`) to place the app.
48
+
49
+ Edit that file to require the `web_task_runner` gem:
50
+
51
+ ```ruby
52
+ # app.rb
53
+
54
+ require 'web_task_runner'
55
+ ```
56
+
57
+ ### Add Jobs To The Task
58
+
59
+ A task may contain many jobs, which can be working on concurrently. When the
60
+ task starts, all the jobs will be carried out, run (and rerun if faild) with
61
+ Sidekiq. The task will end after every job has been done.
62
+
63
+ You can define new jobs by creating a class inheriting
64
+ `WebTaskRunner::TaskWorker`:
65
+
66
+ ```ruby
67
+ # app.rb
68
+
69
+ require 'web_task_runner'
70
+
71
+ class MyWorkOne < WebTaskRunner::TaskWorker
72
+ end
73
+ ```
74
+
75
+ The actual work of that job can should defined in the instance method `#exec`
76
+ of the class:
77
+
78
+ ```ruby
79
+ # app.rb
80
+
81
+ require 'web_task_runner'
82
+
83
+ class MyWorkOne < WebTaskRunner::TaskWorker
84
+ def exec
85
+ # sleep one second for ten times
86
+ 10.times do |i|
87
+ sleep(1)
88
+ raise if Random.rand(100) < 2 # simulate errors
89
+ end
90
+ end
91
+ end
92
+ ```
93
+
94
+ Progress of that work may be reported with the `WebTaskRunner.job_n_progress=`
95
+ method (`n` is the serial number of job, e.g.: `1`) while the job is running:
96
+
97
+ ```ruby
98
+ # app.rb
99
+
100
+ require 'web_task_runner'
101
+
102
+ class MyWorkOne < WebTaskRunner::TaskWorker
103
+ def exec
104
+ # sleep one second for ten times
105
+ 10.times do |i|
106
+ sleep(1)
107
+ raise if Random.rand(100) < 2 # simulate errors
108
+ # report the current progress
109
+ WebTaskRunner.job_1_progress = (i + 1) / 10
110
+ end
111
+ end
112
+ end
113
+ ```
114
+
115
+ At last, append the job to the task using `WebTaskRunner.jobs.<<`:
116
+
117
+ ```ruby
118
+ # app.rb
119
+
120
+ require 'web_task_runner'
121
+
122
+ class MyWorkOne < WebTaskRunner::TaskWorker
123
+ def exec
124
+ # sleep one second for ten times
125
+ 10.times do |i|
126
+ sleep(1)
127
+ raise if Random.rand(100) < 2 # simulate errors
128
+ # report the current progress
129
+ WebTaskRunner.job_1_progress = (i + 1) / 10
130
+ end
131
+ end
132
+ end
133
+
134
+ WebTaskRunner.jobs << MyWorkOne
135
+ ```
136
+
137
+ ### Construct Deployable Application
138
+
139
+ You may need other files to make your application deployable, for instance,
140
+ a `config.ru` Rack configuration file, a `Procfile` to specify process types.
141
+
142
+ The `config.ru` file can be set up like this:
143
+
144
+ ```ruby
145
+ # config.ru
146
+
147
+ require './app' # require your application
148
+ run Rack::URLMap.new('/' => WebTaskRunner)
149
+ ```
150
+
151
+ Sidekiq also provides an web monitoring interface that you can mount. If you
152
+ choose to use it, your `config.ru` may be like this:
153
+
154
+ ```ruby
155
+ # config.ru
156
+
157
+ require './app' # require your application
158
+ require 'sidekiq/web' # require sidekiq web interface
159
+
160
+ # secure the web interface using the API key as password
161
+ Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
162
+ [user, password] == ["admin", ENV['API_KEY']]
163
+ end
164
+
165
+ # mount both WebTaskRunner and Sidekiq::Web
166
+ run Rack::URLMap.new('/' => WebTaskRunner, '/sidekiq' => Sidekiq::Web)
167
+ ```
168
+
169
+ The next will be `Procfile`, which may be like this:
170
+
171
+ ```
172
+ web: bundle exec thin start -p $PORT
173
+ worker: bundle exec sidekiq -c 10 -t 0 -v -r ./app.rb
174
+ ```
175
+
176
+ ### Up And Running
177
+
178
+ Now your application is ready for running, it can be deployed to heroku by a
179
+ `git push`, add an Redis addon, and scale up both web and worker dynos. Or
180
+ run it locally using `foreman`, or even run the processes manually:
181
+
182
+ ```bash
183
+ $ bundle exec thin start -p 5000 & ; bundle exec sidekiq -c 10 -t 0 -v -r ./app.rb &
184
+ ```
185
+
186
+ Then, use the API endpoints to control or monitor the task runner. Each
187
+ request should be called with an `key` parameter containing the same API key
188
+ specified aboved in the `API_KEY` environment variable.
189
+
190
+ To get the current status, visit `/`:
191
+
192
+ ```http
193
+ GET http://localhost:5000/?key=some_secret_key
194
+
195
+ HTTP/1.1 200 OK
196
+ Connection: keep-alive
197
+ Content-Length: 122
198
+ Content-Type: text/html;charset=utf-8
199
+
200
+ {
201
+ "state": "idle",
202
+ "task_started_at": "2015-05-29 15:49:41 +0800",
203
+ "task_finished_at": "2015-05-29 15:49:51 +0800"
204
+ }
205
+ ```
206
+
207
+ To start running the task, visit `/start`.
208
+
209
+ To kill the task that is currently running, visit `/kill`.
210
+
211
+ ## Development
212
+
213
+ After checking out the repo, run `bin/setup` to install dependencies.
214
+ Then, run `bin/console` for an interactive prompt that will allow you
215
+ to experiment.
216
+
217
+ To install this gem onto your local machine, run `bundle exec rake install`.
218
+ To release a new version, update the version number in `version.rb`, and then
219
+ run `bundle exec rake release` to create a git tag for the version, push git
220
+ commits and tags, and push the `.gem` file to
221
+ [rubygems.org](https://rubygems.org).
222
+
223
+ ## Contributing
224
+
225
+ 1. Fork it ( https://github.com/Neson/web_task_runner/fork )
226
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
227
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
228
+ 4. Push to the branch (`git push origin my-new-feature`)
229
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "web_task_runner"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,23 @@
1
+ require 'sinatra'
2
+ require 'sidekiq'
3
+
4
+ class WebTaskRunner < Sinatra::Application
5
+ module RedisModule
6
+ def self.connection
7
+ proc { Redis.new(url: ENV['REDIS_URL']) }
8
+ end
9
+
10
+ def self.redis
11
+ @redis ||= connection.call
12
+ end
13
+ end
14
+ end
15
+
16
+ # Set Redis connections for both Sidekiq server and client
17
+ Sidekiq.configure_server do |config|
18
+ config.redis = ConnectionPool.new(&WebTaskRunner::RedisModule.connection)
19
+ end
20
+
21
+ Sidekiq.configure_client do |config|
22
+ config.redis = ConnectionPool.new(&WebTaskRunner::RedisModule.connection)
23
+ end
@@ -0,0 +1,39 @@
1
+ require 'sinatra'
2
+ require 'sidekiq'
3
+ require 'sidekiq-status'
4
+
5
+ require_relative '../web_task_runner.rb'
6
+
7
+ class WebTaskRunner < Sinatra::Application
8
+ class TaskWorker
9
+ include Sidekiq::Worker
10
+ include Sidekiq::Status::Worker
11
+
12
+ def perform
13
+ return if WebTaskRunner.current_state == 'idle'
14
+
15
+ exec
16
+
17
+ puts "Job ##{job_number} done."
18
+ WebTaskRunner.work_ended
19
+ end
20
+
21
+ def job_number
22
+ job_number = 0
23
+ klass = self.class
24
+ WebTaskRunner.jobs.each_with_index do |job, i|
25
+ if job == klass
26
+ job_number = i + 1
27
+ break
28
+ end
29
+ end
30
+ job_number
31
+ end
32
+
33
+ def exec
34
+ puts <<-EOF
35
+ Define the work in #{self.class}#exec!
36
+ EOF
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,5 @@
1
+ require 'sinatra'
2
+
3
+ class WebTaskRunner < Sinatra::Application
4
+ VERSION = "0.0.1"
5
+ end
@@ -0,0 +1,211 @@
1
+ $stdout.sync = true
2
+
3
+ require 'sinatra'
4
+ require 'dotenv'
5
+ Dotenv.load
6
+
7
+ require "web_task_runner/version"
8
+ require "web_task_runner/redis_module"
9
+ require "web_task_runner/task_worker"
10
+
11
+ class WebTaskRunner < Sinatra::Application
12
+ @@jobs = []
13
+
14
+ def self.jobs
15
+ @@jobs
16
+ end
17
+
18
+ # GET /?key=<api_key> - retrieve current state of the crawler
19
+ get '/' do
20
+ # Authorize the request
21
+ error 401, JSON.pretty_generate(error: 'Unauthorized') and \
22
+ return if ENV['API_KEY'] != params[:key]
23
+
24
+ return JSON.pretty_generate(current_info)
25
+ end
26
+
27
+ # GET /start?key=<api_key> - start the crawler if idle
28
+ get '/start' do
29
+ # Authorize the request
30
+ error 401, JSON.pretty_generate(error: 'Unauthorized') and \
31
+ return if ENV['API_KEY'] != params[:key]
32
+
33
+ start_task_if_idle
34
+
35
+ return 'start'
36
+ end
37
+
38
+ # GET /kill?key=<api_key> - kill the working job
39
+ get '/kill' do
40
+ # Authorize the request
41
+ error 401, JSON.pretty_generate(error: 'Unauthorized') and \
42
+ return if ENV['API_KEY'] != params[:key]
43
+
44
+ kill_task
45
+
46
+ return 'kill'
47
+ end
48
+
49
+ # Report that a worker has done working, call this in each worker after
50
+ # the work has done
51
+ def self.work_ended(all: false)
52
+ if all
53
+ WebTaskRunner::RedisModule.redis.set('task:working_jobs', 0)
54
+ else
55
+ # decrease the working workers count
56
+ WebTaskRunner::RedisModule.redis.decr('task:working_jobs')
57
+ end
58
+
59
+ # set the state to idle if all the works has been done
60
+ if WebTaskRunner::RedisModule.redis.get('task:working_jobs').to_i < 1
61
+ WebTaskRunner::RedisModule.redis.set('task:state', 'idle')
62
+ WebTaskRunner::RedisModule.redis.set('task:finished_at', Time.now)
63
+ end
64
+ end
65
+
66
+ # Sets the progress of the current work
67
+ # It can be used like this in the worker: +WebTaskRunner.work_2_progress = 0.8+
68
+ 1000.times do |i|
69
+ i += 1
70
+ define_singleton_method("job_#{i}_progress=") do |progress|
71
+ WebTaskRunner::RedisModule.redis.set("task:worker_#{i}_progress", progress)
72
+ end
73
+ end
74
+
75
+ # Starts (or kill and restart) the task
76
+ def self.start_task
77
+ kill_task
78
+ WebTaskRunner::RedisModule.redis.set('task:state', 'working')
79
+ WebTaskRunner::RedisModule.redis.set('task:started_at', Time.now)
80
+
81
+ # Set the count of worker that should be started
82
+ jobs_count = @@jobs.count
83
+
84
+ # Start the worker here
85
+ @@jobs.each(&:perform_async)
86
+
87
+ WebTaskRunner::RedisModule.redis.set('task:task_jobs', jobs_count)
88
+ WebTaskRunner::RedisModule.redis.set('task:working_jobs', jobs_count)
89
+
90
+ # Reset the progress of each worker
91
+ jobs_count.times do |i|
92
+ i -= 1
93
+ WebTaskRunner::RedisModule.redis.set("task:worker_#{i}_progress", 0)
94
+ end
95
+ end
96
+
97
+ def start_task # :nodoc:
98
+ WebTaskRunner.start_task
99
+ end
100
+
101
+ # Starts the task if it's not running
102
+ def self.start_task_if_idle
103
+ return unless current_state == 'idle'
104
+ start_task
105
+ end
106
+
107
+ def start_task_if_idle # :nodoc:
108
+ WebTaskRunner.start_task_if_idle
109
+ end
110
+
111
+ # Kills the running task
112
+ def self.kill_task
113
+ ps = Sidekiq::ProcessSet.new
114
+ ps.each do |p|
115
+ p.stop! if p['busy'] > 0
116
+ end
117
+ sleep(0.5)
118
+ Sidekiq::Queue.new.clear
119
+ Sidekiq::ScheduledSet.new.clear
120
+ Sidekiq::RetrySet.new.clear
121
+ WebTaskRunner.work_ended(all: true)
122
+ end
123
+
124
+ def kill_task # :nodoc:
125
+ WebTaskRunner.kill_task
126
+ end
127
+
128
+ # Get the current state
129
+ def self.current_state
130
+ WebTaskRunner::RedisModule.redis.get('task:state') || 'idle'
131
+ end
132
+
133
+ def current_state # :nodoc:
134
+ WebTaskRunner.current_state
135
+ end
136
+
137
+ # Get the task progress
138
+ def self.task_progress
139
+ return nil if current_state == 'idle'
140
+ task_jobs = WebTaskRunner::RedisModule.redis.get('task:task_jobs').to_i
141
+ return nil unless task_jobs
142
+ total_progress = 0.0
143
+
144
+ task_jobs.times do |i|
145
+ i += 1
146
+ total_progress += WebTaskRunner::RedisModule.redis.get("task:worker_#{i}_progress").to_f
147
+ end
148
+
149
+ total_progress / task_jobs.to_f
150
+ end
151
+
152
+ def task_progress # :nodoc:
153
+ WebTaskRunner.task_progress
154
+ end
155
+
156
+ # Get the time when the task last started
157
+ def self.task_started_at
158
+ try_to_parse_date_from_redis('task:started_at')
159
+ end
160
+
161
+ def task_started_at # :nodoc:
162
+ WebTaskRunner.task_started_at
163
+ end
164
+
165
+ # Get the time when the task last finished
166
+ def self.task_finished_at
167
+ return nil if current_state != 'idle'
168
+ try_to_parse_date_from_redis('task:finished_at')
169
+ end
170
+
171
+ def task_finished_at # :nodoc:
172
+ WebTaskRunner.task_finished_at
173
+ end
174
+
175
+ # Get the info of the task
176
+ def self.current_info
177
+ info = { state: current_state }
178
+ info[:task_progress] = task_progress if task_progress
179
+ info[:task_started_at] = task_started_at if task_started_at
180
+ info[:task_finished_at] = task_finished_at if task_finished_at
181
+
182
+ info
183
+ end
184
+
185
+ def current_info # :nodoc:
186
+ WebTaskRunner.current_info
187
+ end
188
+
189
+ # Get the status of the task runner
190
+ def self.current_status
191
+ info = { state: current_state }
192
+
193
+ info
194
+ end
195
+
196
+ def current_status # :nodoc:
197
+ WebTaskRunner.current_status
198
+ end
199
+
200
+ private
201
+
202
+ def self.try_to_parse_date_from_redis(key)
203
+ Time.parse(WebTaskRunner::RedisModule.redis.get(key))
204
+ rescue
205
+ nil
206
+ end
207
+
208
+ def try_to_parse_date_from_redis(key)
209
+ WebTaskRunner.try_to_parse_date_from_redis(key)
210
+ end
211
+ end
@@ -0,0 +1,42 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'web_task_runner/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "web_task_runner"
8
+ spec.version = WebTaskRunner::VERSION
9
+ spec.authors = ["Neson"]
10
+ spec.email = ["neson@dex.tw"]
11
+
12
+ spec.summary = %q{Web wrapper to run a specific task.}
13
+ spec.description = %q{Web wrapper to run a specific task with Sidekiq. Provides HTTP API to start, stop, get status of the task running in background, and is deployable to cloud platforms like Heroku.}
14
+ spec.homepage = "http://github.com/Neson/web_task_runner"
15
+
16
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
+ # delete this section to allow pushing this gem to any host.
18
+ # if spec.respond_to?(:metadata)
19
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
20
+ # else
21
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ # end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ # Web framework and server
30
+ spec.add_dependency "sinatra", "~> 1.4.6"
31
+ spec.add_dependency "thin"
32
+
33
+ # Job runner
34
+ spec.add_dependency "sidekiq", "~> 3.3.4"
35
+ spec.add_dependency "sidekiq-status"
36
+
37
+ # Utilities
38
+ spec.add_dependency "dotenv"
39
+
40
+ spec.add_development_dependency "bundler", "~> 1.9"
41
+ spec.add_development_dependency "rake", "~> 10.0"
42
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: web_task_runner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Neson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.4.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: thin
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sidekiq
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.3.4
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.3.4
55
+ - !ruby/object:Gem::Dependency
56
+ name: sidekiq-status
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dotenv
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.9'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.9'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ description: Web wrapper to run a specific task with Sidekiq. Provides HTTP API to
112
+ start, stop, get status of the task running in background, and is deployable to
113
+ cloud platforms like Heroku.
114
+ email:
115
+ - neson@dex.tw
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - ".gitignore"
121
+ - ".rspec"
122
+ - ".travis.yml"
123
+ - Gemfile
124
+ - README.md
125
+ - Rakefile
126
+ - bin/console
127
+ - bin/setup
128
+ - lib/web_task_runner.rb
129
+ - lib/web_task_runner/redis_module.rb
130
+ - lib/web_task_runner/task_worker.rb
131
+ - lib/web_task_runner/version.rb
132
+ - web_task_runner.gemspec
133
+ homepage: http://github.com/Neson/web_task_runner
134
+ licenses: []
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.4.6
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: Web wrapper to run a specific task.
156
+ test_files: []