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 +4 -4
- data/README.md +76 -8
- data/lib/web_task_runner.rb +33 -11
- data/lib/web_task_runner/redis_module.rb +9 -1
- data/lib/web_task_runner/version.rb +1 -1
- data/web_task_runner.gemspec +1 -0
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa3d96c91c52ee015b141cdfd3a166f9ab0ae680
|
4
|
+
data.tar.gz: 21bd106643b4e50183b9fa5232cff82f2902fc1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
#
|
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
|
|
data/lib/web_task_runner.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
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 /
|
41
|
-
get '/
|
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
|
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
|
207
|
+
# Get the status of the task
|
192
208
|
def self.current_status
|
193
|
-
|
209
|
+
task_status = WebTaskRunner::RedisModule.redis.get('task:status')
|
210
|
+
return {} unless task_status
|
194
211
|
|
195
|
-
|
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
|
-
|
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
|
data/web_task_runner.gemspec
CHANGED
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
|
+
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
|