blue_colr 0.1.2 → 0.1.3
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.
- data/README.rdoc +2 -2
- data/bin/bluecolrd +2 -4
- data/lib/blue_colr.rb +64 -58
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -49,8 +49,8 @@ http://github.com/downloads/jablan/blue_colr/readme_example.png
|
|
49
49
|
|
50
50
|
== Requirements and Configuration
|
51
51
|
|
52
|
-
In order to access the database, blue_colr requires sequel
|
53
|
-
don't have it, its gem will be installed along with blue_colr.
|
52
|
+
In order to access the database, blue_colr requires sequel[http://sequel.rubyforge.org/]
|
53
|
+
ORM library, if you don't have it, its gem will be installed along with blue_colr.
|
54
54
|
|
55
55
|
Blue_colr uses a relational database to simulate a process queue so you will have
|
56
56
|
to provide one. It relies on two tables, named +process_items+ and
|
data/bin/bluecolrd
CHANGED
@@ -119,9 +119,8 @@ def run process, running_state
|
|
119
119
|
:exit_code => exitstatus,
|
120
120
|
:ended_at => Time.now
|
121
121
|
)
|
122
|
-
|
123
|
-
|
124
|
-
# logger.info "Process ended: id #{process[:id]} #{$?}"
|
122
|
+
logger.info "Process ended: id #{process[:id]} #{$?}"
|
123
|
+
logger.error(@error_log_msg % process.to_hash) unless ok
|
125
124
|
end
|
126
125
|
end
|
127
126
|
|
@@ -184,7 +183,6 @@ begin
|
|
184
183
|
# end
|
185
184
|
# exit 1
|
186
185
|
rescue Exception => ex
|
187
|
-
p ex.class
|
188
186
|
logger.fatal(ex.to_s) if logger
|
189
187
|
puts "#{ex.to_s} ==>"
|
190
188
|
puts ex.backtrace.join("\n")
|
data/lib/blue_colr.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
# This class provides a simple DSL for enqueuing processes to the database
|
2
|
-
# in particular order.
|
3
|
-
|
4
1
|
require 'rubygems'
|
5
|
-
require 'date'
|
2
|
+
#require 'date'
|
6
3
|
require 'logger'
|
7
4
|
require 'ostruct'
|
8
5
|
require 'optparse'
|
@@ -43,6 +40,7 @@ class BlueColr
|
|
43
40
|
@log ||= Logger.new('process_daemon')
|
44
41
|
end
|
45
42
|
|
43
|
+
# Configuration hash read from yaml config file
|
46
44
|
def conf
|
47
45
|
unless @conf
|
48
46
|
parse_command_line unless @args
|
@@ -60,13 +58,15 @@ class BlueColr
|
|
60
58
|
@conf
|
61
59
|
end
|
62
60
|
|
61
|
+
# Sequel DB URI connection string
|
63
62
|
def db_uri
|
64
63
|
unless @db_uri # get the config from command line
|
65
64
|
@db_uri = self.conf['db_url']
|
66
65
|
end
|
67
66
|
@db_uri
|
68
67
|
end
|
69
|
-
|
68
|
+
|
69
|
+
# Sequel DB connection instance
|
70
70
|
def db
|
71
71
|
unless @db # not connected
|
72
72
|
@db = Sequel.connect(self.db_uri, :logger => self.log)
|
@@ -74,38 +74,34 @@ class BlueColr
|
|
74
74
|
@db
|
75
75
|
end
|
76
76
|
|
77
|
-
#
|
77
|
+
# Default options to use when launching a process - every field maps to a
|
78
78
|
# column in process_items table
|
79
79
|
def default_options
|
80
80
|
@default_options ||= OpenStruct.new
|
81
81
|
end
|
82
82
|
|
83
|
-
#
|
83
|
+
# Local hash used to store misc runtime options
|
84
84
|
def options
|
85
85
|
@options ||= OpenStruct.new
|
86
86
|
end
|
87
87
|
|
88
|
+
# Map of states that processes pass through (Pending -> Running -> Ok / Error)
|
88
89
|
def statemap
|
89
90
|
@statemap ||= conf['statemap'] || DEFAULT_STATEMAP
|
90
91
|
end
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
93
|
+
# # Create new sequential block (see instance method with the same name)
|
94
|
+
# def sequential &block
|
95
|
+
# self.new.sequential &block
|
96
|
+
# end
|
95
97
|
|
96
|
-
|
97
|
-
|
98
|
-
|
98
|
+
# # Create new parallel block (see instance method with the same name)
|
99
|
+
# def parallel &block
|
100
|
+
# self.new.parallel &block
|
101
|
+
# end
|
99
102
|
|
100
|
-
#
|
101
|
-
# command line parameter extraction
|
102
|
-
def custom_args &block
|
103
|
-
@custom_args_block = block
|
104
|
-
end
|
105
|
-
|
106
|
-
# launch a set of tasks, provided within a given block
|
103
|
+
# Usually the root method for launcing a set of tasks.
|
107
104
|
def launch &block
|
108
|
-
|
109
105
|
worker = self.new
|
110
106
|
db.transaction do
|
111
107
|
worker.instance_eval &block
|
@@ -113,12 +109,15 @@ class BlueColr
|
|
113
109
|
worker
|
114
110
|
end
|
115
111
|
|
116
|
-
#
|
112
|
+
# Run a set of tasks (launch it and wait until the last one finishes). exit with returned exitcode.
|
117
113
|
def run &block
|
118
114
|
worker = launch &block
|
119
115
|
exit worker.wait
|
120
116
|
end
|
121
117
|
|
118
|
+
# Parse command line arguments. You should call it explicitly if you need to submit some
|
119
|
+
# additional custom parameters. Otherwise it will be called automatically in order to get
|
120
|
+
# parameters needed for running, such as database connection string.
|
122
121
|
def parse_command_line &block
|
123
122
|
data = {}
|
124
123
|
|
@@ -152,7 +151,7 @@ class BlueColr
|
|
152
151
|
|
153
152
|
# state related methods
|
154
153
|
|
155
|
-
#
|
154
|
+
# Get the next state from pending, given current state and state of all "parent" processes
|
156
155
|
def state_from_pending current_state, parent_states
|
157
156
|
new_state, _ = self.statemap['on_pending'][current_state].find { |_, required_parent_states|
|
158
157
|
(parent_states - required_parent_states).empty?
|
@@ -160,49 +159,37 @@ class BlueColr
|
|
160
159
|
new_state
|
161
160
|
end
|
162
161
|
|
163
|
-
#
|
162
|
+
# Get the next state from running, given current state and whether the command has finished successfully
|
164
163
|
def state_from_running current_state, ok
|
165
164
|
self.statemap['on_running'][current_state][ok ? 'ok' : 'error']
|
166
165
|
end
|
167
166
|
|
168
|
-
#
|
167
|
+
# Get the next state to get upon restart, given the current state
|
169
168
|
def state_on_restart current_state
|
170
169
|
self.statemap['on_restart'][current_state]
|
171
170
|
end
|
172
171
|
|
173
|
-
#
|
172
|
+
# Get all possible pending states
|
174
173
|
def get_pending_states
|
175
174
|
self.statemap['on_pending'].map{|state, _| state}
|
176
175
|
end
|
177
176
|
|
178
|
-
#
|
177
|
+
# Get all possible error states
|
179
178
|
def get_error_states
|
180
179
|
self.statemap['on_running'].map{|_, new_states| new_states['error']}
|
181
180
|
end
|
182
181
|
|
183
|
-
#
|
182
|
+
# Get all possible ok states
|
184
183
|
def get_ok_states
|
185
184
|
self.statemap['on_running'].map{|_, new_states| new_states['ok']}
|
186
185
|
end
|
187
186
|
|
188
187
|
end # class methods
|
189
188
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
@type = type
|
194
|
-
@waitfor = waitfor
|
195
|
-
@result = []
|
196
|
-
@all_ids = [] # list of all ids of processes enqueued, used if waiting
|
197
|
-
end
|
198
|
-
|
199
|
-
def db
|
200
|
-
self.class.db
|
201
|
-
end
|
189
|
+
#
|
190
|
+
#attr_reader :all_ids
|
191
|
+
attr_reader :result
|
202
192
|
|
203
|
-
def log
|
204
|
-
self.class.log
|
205
|
-
end
|
206
193
|
|
207
194
|
# All processes enqueued within the given block should be executed sequentially,
|
208
195
|
# i.e. one after another.
|
@@ -216,19 +203,6 @@ class BlueColr
|
|
216
203
|
exec :parallel, &block
|
217
204
|
end
|
218
205
|
|
219
|
-
def exec type = :sequential, &block
|
220
|
-
g = self.class.new type, @waitfor
|
221
|
-
g.instance_eval &block
|
222
|
-
ids = g.result
|
223
|
-
if @type == :sequential
|
224
|
-
@waitfor = ids
|
225
|
-
@result = ids
|
226
|
-
else
|
227
|
-
@result += ids
|
228
|
-
end
|
229
|
-
@result
|
230
|
-
end
|
231
|
-
|
232
206
|
def enqueue cmd, waitfor = [], opts = {}
|
233
207
|
id = nil
|
234
208
|
opts = {status: DEFAULT_PENDING_STATE}.merge(opts)
|
@@ -247,7 +221,7 @@ class BlueColr
|
|
247
221
|
id
|
248
222
|
end
|
249
223
|
|
250
|
-
#
|
224
|
+
# Enqueues a single command +cmd+.
|
251
225
|
#
|
252
226
|
# == Parameters
|
253
227
|
# cmd::
|
@@ -267,7 +241,9 @@ class BlueColr
|
|
267
241
|
@result
|
268
242
|
end
|
269
243
|
|
270
|
-
#
|
244
|
+
# Waits for all enqueued processes to finish. The default behaviour for BlueColr is to enqueue commands
|
245
|
+
# and exit. If for any reason you need to wait for the commands to finish execution, you can call this method
|
246
|
+
# which will wait until all enqueued processes are finished (either with Ok or error state).
|
271
247
|
def wait
|
272
248
|
log.info 'Waiting for all processes to finish'
|
273
249
|
loop do
|
@@ -278,4 +254,34 @@ class BlueColr
|
|
278
254
|
sleep 10
|
279
255
|
end
|
280
256
|
end
|
257
|
+
|
258
|
+
private
|
259
|
+
|
260
|
+
def initialize type = :sequential, waitfor = []
|
261
|
+
@type = type
|
262
|
+
@waitfor = waitfor
|
263
|
+
@result = []
|
264
|
+
@all_ids = [] # list of all ids of processes enqueued, used if waiting
|
265
|
+
end
|
266
|
+
|
267
|
+
def db
|
268
|
+
self.class.db
|
269
|
+
end
|
270
|
+
|
271
|
+
def log
|
272
|
+
self.class.log
|
273
|
+
end
|
274
|
+
|
275
|
+
def exec type = :sequential, &block
|
276
|
+
g = self.class.new type, @waitfor
|
277
|
+
g.instance_eval &block
|
278
|
+
ids = g.result
|
279
|
+
if @type == :sequential
|
280
|
+
@waitfor = ids
|
281
|
+
@result = ids
|
282
|
+
else
|
283
|
+
@result += ids
|
284
|
+
end
|
285
|
+
@result
|
286
|
+
end
|
281
287
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blue_colr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mladen Jablanovic
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-10-
|
18
|
+
date: 2011-10-18 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|