web_task_runner 0.0.4 → 0.0.5

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 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