web_task_runner 0.0.4 → 0.0.5

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: 3004d490f604c0e133bc23d31fd9d9383677d95b
4
- data.tar.gz: 14aac705ac0f347993dcb364f588638571dbd313
3
+ metadata.gz: aa3d96c91c52ee015b141cdfd3a166f9ab0ae680
4
+ data.tar.gz: 21bd106643b4e50183b9fa5232cff82f2902fc1b
5
5
  SHA512:
6
- metadata.gz: da3fa726366004f40470992d2da10d389f93e6af3dca83dcc4000de83b9f1e82e094e2944cccda708eaa49955a75bcb1d64fccf98e140e20d2989f3548257caf
7
- data.tar.gz: baaa274cb01c197e4880ecaa2cf10c9a0ac5f685e83f2f8da6b1814e98cb85097c70e7bc4b43b6069fb075c0636f215be6f4cf7264853bfdbb44b813ee1de758
6
+ metadata.gz: 2118e07ec979f23255dcb1ab83ec17a58d131a0fcdf3033bd1ffcb0bd1e7f95ec4f7175939e5195f4863d3fb905389c67f058ef0f3e21c469cb0f3529270318d
7
+ data.tar.gz: a9c40f240304c6543d0d8bc6f38c14c9b3274c89223caf510c64b5514282ebb78dabcf2a4af9e0a181c0a2d6f537fdb1c823a7f6f1418d80346f1121059bf317
data/README.md CHANGED
@@ -26,6 +26,78 @@ And then execute:
26
26
  Redis is required to run the background jobs. Make sure you have one, and set
27
27
  the `REDIS_URL` environment variable to the Redis URL.
28
28
 
29
+ ## Usage
30
+
31
+ Just `require 'web_task_runner'` and append jobs to it
32
+ (`WebTaskRunner.jobs << SomeWork`). Then you'll have a Rack app `WebTaskRunner`
33
+ providing web APIs ready to be mounted. Configurations `REDIS_URL`, `API_KEY`
34
+ and `REDIS_NAMESPACE` can be set through environment variables.
35
+
36
+ Please refer the [Getting Start](#getting-start) section for more details.
37
+
38
+ ### API Endpoints
39
+
40
+ Note that all APIs has been secured with the `API_KEY`. Each request should
41
+ pass the matching `API_KEY` with the `key` parameter
42
+ (e.g.: `https://example.app/?key=secreat_key`), otherwise an `401 Unauthorized`
43
+ error will be returned.
44
+
45
+ #### `GET /`
46
+
47
+ Returns the information of the task runner.
48
+
49
+ #### `GET /status`
50
+
51
+ Returns the current (or last) status of running task.
52
+
53
+ ```json
54
+ HTTP/1.1 200 OK
55
+
56
+ {
57
+ "status": "processing",
58
+ "progress": 0.52,
59
+ "started_at": "2015-05-29 22:36:35 +0000"
60
+ }
61
+ ```
62
+
63
+ - status: can be `processing`, `ok` or `error`
64
+ - progress: an float representing the current working progress, presented only
65
+ if the task is currently in progress
66
+ - started_at: time of when the task has been started
67
+ - finished_at: time of when the task has finished, presented only
68
+ if the last task is finished
69
+
70
+ #### `GET /start`
71
+
72
+ Start to run the task (if the task is not currently running).
73
+
74
+ ```json
75
+ HTTP/1.1 202 Accepted
76
+
77
+ {
78
+ "status": "processing",
79
+ "link": "https://example.app/status?key=secreat_key"
80
+ }
81
+ ```
82
+
83
+ - status: must be `processing`, since the task will be run asynchronously
84
+ - link: URL for monitoring the started task
85
+
86
+ #### `GET /stop`
87
+
88
+ Force stop the current running task.
89
+
90
+ ```json
91
+ HTTP/1.1 200 OK
92
+
93
+ {
94
+ "status": "error",
95
+ "link": "https://example.app/status?key=secreat_key",
96
+ "started_at": "2015-05-29 22:36:35 +0000",
97
+ "finished_at": "2015-05-29 23:12:48 +0000"
98
+ }
99
+ ```
100
+
29
101
  ## Getting Start
30
102
 
31
103
  Create and `cd` into a new folder to place the task runner app. After adding
@@ -41,6 +113,7 @@ app to run, you can set it using `$ export` or save them into a file called
41
113
 
42
114
  - `REDIS_URL`: specify the Redis to connect to
43
115
  - `API_KEY`: chose a secret key for accessing the web API
116
+ - `REDIS_NAMESPACE`: _(optional)_ namespacing Redis keys
44
117
 
45
118
  ### Create The App
46
119
 
@@ -106,7 +179,7 @@ class MyWorkOne < WebTaskRunner::TaskWorker
106
179
  sleep(1)
107
180
  raise if Random.rand(100) < 2 # simulate errors
108
181
  # report the current progress
109
- WebTaskRunner.job_1_progress = (i + 1) / 10
182
+ WebTaskRunner.job_1_progress = (i + 1) / 10.0
110
183
  end
111
184
  end
112
185
  end
@@ -121,16 +194,11 @@ require 'web_task_runner'
121
194
 
122
195
  class MyWorkOne < WebTaskRunner::TaskWorker
123
196
  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
197
+ # ...
131
198
  end
132
199
  end
133
200
 
201
+ # append the job to task runner
134
202
  WebTaskRunner.jobs << MyWorkOne
135
203
  ```
136
204
 
@@ -17,7 +17,7 @@ class WebTaskRunner < Sinatra::Application
17
17
  @@jobs
18
18
  end
19
19
 
20
- # GET /?key=<api_key> - retrieve current state of the crawler
20
+ # GET /?key=<api_key> - retrieve current state of the task runner
21
21
  get '/' do
22
22
  # Authorize the request
23
23
  error 401, JSON.pretty_generate(error: 'Unauthorized') and \
@@ -26,7 +26,16 @@ class WebTaskRunner < Sinatra::Application
26
26
  return JSON.pretty_generate(current_info)
27
27
  end
28
28
 
29
- # GET /start?key=<api_key> - start the crawler if idle
29
+ # GET /?key=<api_key> - retrieve current status of the task
30
+ get '/status' do
31
+ # Authorize the request
32
+ error 401, JSON.pretty_generate(error: 'Unauthorized') and \
33
+ return if ENV['API_KEY'] != params[:key]
34
+
35
+ return JSON.pretty_generate(current_status)
36
+ end
37
+
38
+ # GET /start?key=<api_key> - start the task if idle
30
39
  get '/start' do
31
40
  # Authorize the request
32
41
  error 401, JSON.pretty_generate(error: 'Unauthorized') and \
@@ -34,18 +43,21 @@ class WebTaskRunner < Sinatra::Application
34
43
 
35
44
  start_task_if_idle
36
45
 
37
- return 'start'
46
+ link = "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}/status?key=#{params[:key]}"
47
+
48
+ status 202
49
+ return JSON.pretty_generate({ status: 'processing', link: link })
38
50
  end
39
51
 
40
- # GET /kill?key=<api_key> - kill the working job
41
- get '/kill' do
52
+ # GET /stop?key=<api_key> - kill the working task
53
+ get '/stop' do
42
54
  # Authorize the request
43
55
  error 401, JSON.pretty_generate(error: 'Unauthorized') and \
44
56
  return if ENV['API_KEY'] != params[:key]
45
57
 
46
58
  kill_task
47
59
 
48
- return 'kill'
60
+ return JSON.pretty_generate(current_status)
49
61
  end
50
62
 
51
63
  # Report that a job has been done, call this in each job after
@@ -61,6 +73,7 @@ class WebTaskRunner < Sinatra::Application
61
73
  # set the state to idle if all the works has been done
62
74
  if WebTaskRunner::RedisModule.redis.get('task:working_jobs').to_i < 1
63
75
  WebTaskRunner::RedisModule.redis.set('task:state', 'idle')
76
+ WebTaskRunner::RedisModule.redis.set('task:status', 'ok')
64
77
  WebTaskRunner::RedisModule.redis.set('task:finished_at', Time.now)
65
78
  end
66
79
  end
@@ -78,6 +91,7 @@ class WebTaskRunner < Sinatra::Application
78
91
  def self.start_task
79
92
  kill_task
80
93
  WebTaskRunner::RedisModule.redis.set('task:state', 'working')
94
+ WebTaskRunner::RedisModule.redis.set('task:status', 'processing')
81
95
  WebTaskRunner::RedisModule.redis.set('task:started_at', Time.now)
82
96
 
83
97
  # Set the count of jobs that should be started
@@ -113,14 +127,16 @@ class WebTaskRunner < Sinatra::Application
113
127
  # Kills the running task
114
128
  def self.kill_task
115
129
  ps = Sidekiq::ProcessSet.new
130
+ killed_count = 0
116
131
  ps.each do |p|
117
- p.stop! if p['busy'] > 0
132
+ p.stop! and killed_count += 1 if p['busy'] > 0
118
133
  end
119
134
  sleep(0.5)
120
135
  Sidekiq::Queue.new.clear
121
136
  Sidekiq::ScheduledSet.new.clear
122
137
  Sidekiq::RetrySet.new.clear
123
138
  WebTaskRunner.job_ended(all: true)
139
+ WebTaskRunner::RedisModule.redis.set('task:status', 'error') if killed_count > 0
124
140
  end
125
141
 
126
142
  def kill_task # :nodoc:
@@ -174,7 +190,7 @@ class WebTaskRunner < Sinatra::Application
174
190
  WebTaskRunner.task_finished_at
175
191
  end
176
192
 
177
- # Get the info of the task
193
+ # Get the info of the task runner
178
194
  def self.current_info
179
195
  info = { state: current_state }
180
196
  info[:task_progress] = task_progress if task_progress
@@ -188,11 +204,17 @@ class WebTaskRunner < Sinatra::Application
188
204
  WebTaskRunner.current_info
189
205
  end
190
206
 
191
- # Get the status of the task runner
207
+ # Get the status of the task
192
208
  def self.current_status
193
- info = { state: current_state }
209
+ task_status = WebTaskRunner::RedisModule.redis.get('task:status')
210
+ return {} unless task_status
194
211
 
195
- info
212
+ status = { status: task_status }
213
+ status[:progress] = task_progress if task_progress && task_status == 'processing'
214
+ status[:started_at] = task_started_at if task_started_at
215
+ status[:finished_at] = task_finished_at if task_finished_at
216
+
217
+ status
196
218
  end
197
219
 
198
220
  def current_status # :nodoc:
@@ -1,10 +1,18 @@
1
1
  require 'sinatra'
2
2
  require 'sidekiq'
3
+ require 'redis-namespace'
3
4
 
4
5
  class WebTaskRunner < Sinatra::Application
5
6
  module RedisModule
6
7
  def self.connection
7
- proc { Redis.new(url: ENV['REDIS_URL']) }
8
+ if ENV['REDIS_NAMESPACE']
9
+ proc do
10
+ redis_c = Redis.new(url: ENV['REDIS_URL'])
11
+ Redis::Namespace.new(ENV['REDIS_NAMESPACE'], redis: redis_c)
12
+ end
13
+ else
14
+ proc { Redis.new(url: ENV['REDIS_URL']) }
15
+ end
8
16
  end
9
17
 
10
18
  def self.redis
@@ -1,3 +1,3 @@
1
1
  class WebTaskRunnerVersion
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
33
33
  # Job runner
34
34
  spec.add_dependency "sidekiq", "~> 3.3.4"
35
35
  spec.add_dependency "sidekiq-status"
36
+ spec.add_dependency "redis-namespace"
36
37
 
37
38
  # Utilities
38
39
  spec.add_dependency "dotenv"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web_task_runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neson
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: redis-namespace
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'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: dotenv
71
85
  requirement: !ruby/object:Gem::Requirement