flor 0.9.2 → 0.9.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.
@@ -51,7 +51,7 @@ class Flor::Pro::Task < Flor::Procedure
51
51
  # "clean up" assign: 'alan'
52
52
  # alan task: 'clean up'
53
53
 
54
- #@executor.unit.tasker.has_tasker?(@executor.exid, key)
54
+ #@executor.unit.has_tasker?(@executor.exid, key)
55
55
 
56
56
  ni = att(nil)
57
57
  ta = att('by', 'for', 'assign')
data/lib/flor/unit.rb CHANGED
@@ -38,7 +38,8 @@ require 'flor/unit/waiter'
38
38
  require 'flor/unit/scheduler'
39
39
  require 'flor/unit/models'
40
40
  require 'flor/unit/loader'
41
- require 'flor/unit/tasker'
41
+ require 'flor/unit/ganger'
42
+ require 'flor/unit/taskers'
42
43
 
43
44
  Flor.load_procedures('punit')
44
45
 
@@ -28,6 +28,7 @@ module Flor
28
28
  class UnitExecutor < Flor::Executor
29
29
 
30
30
  attr_reader :exid
31
+ attr_reader :consumed
31
32
 
32
33
  def initialize(unit, exid)
33
34
 
@@ -66,7 +67,7 @@ module Flor
66
67
 
67
68
  def do_run
68
69
 
69
- log_run_start if @unit.conf['log_run']
70
+ @unit.logger.log_run_start(self)
70
71
 
71
72
  counter_next('runs')
72
73
 
@@ -91,9 +92,6 @@ module Flor
91
92
  ms = process(m)
92
93
 
93
94
  @consumed << m
94
- #
95
- #@consumed << m unless ms.include?(m)
96
- # TODO what if msg is held / pushed back?
97
95
 
98
96
  ims, oms = ms.partition { |m| m['exid'] == @exid }
99
97
  # qui est "in", qui est "out"?
@@ -112,7 +110,7 @@ module Flor
112
110
  @unit.storage.put_execution(@execution)
113
111
  @unit.storage.put_messages(@messages)
114
112
 
115
- log_run_end(t0) if @unit.conf['log_run']
113
+ @unit.logger.log_run_end(self, t0)
116
114
 
117
115
  @consumed.clear
118
116
 
@@ -130,7 +128,6 @@ module Flor
130
128
  "#{self.class}#do_run()", exc, "(dumping to #{fn})")
131
129
 
132
130
  File.open(fn, 'wb') do |f|
133
- #f.puts(JSON.pretty_generate({
134
131
  f.puts(Flor.to_pretty_s({
135
132
  execution: @execution,
136
133
  messages: @messages,
@@ -145,7 +142,8 @@ module Flor
145
142
  f.puts(on_do_run_exc(exc))
146
143
  end
147
144
 
148
- puts on_do_run_exc(exc)
145
+ #puts on_do_run_exc(exc)
146
+ # dump notification above
149
147
  end
150
148
 
151
149
  def schedule(message)
@@ -165,60 +163,6 @@ module Flor
165
163
  [ m ]
166
164
  end
167
165
 
168
- def log_run_start
169
-
170
- _c = Flor.colours
171
-
172
- s = StringIO.new
173
-
174
- s << _c.dg
175
- s << " /--- #{_c.lg}run starts#{_c.dg} "
176
- s << "#{self.class} #{self.object_id} #{@exid}"
177
- s << "\n | "
178
- s << { thread: Thread.current.object_id }.inspect
179
- s << "\n | "
180
- s << {
181
- counters: @execution['counters'],
182
- nodes: @execution['nodes'].size,
183
- size: @execution['size']
184
- }.inspect
185
- s << _c.rs
186
-
187
- puts s.string
188
- end
189
-
190
- def log_run_end(t0)
191
-
192
- _c = Flor.colours
193
-
194
- s = StringIO.new
195
-
196
- s << _c.dg
197
- s << " | run ends #{self.class} #{self.object_id} #{@exid}"
198
- s << "\n | "; s << { took: Time.now - t0 }.inspect
199
- s << "\n | "; s << {
200
- thread: Thread.current.object_id,
201
- consumed: @consumed.size,
202
- traps: @traps.size,
203
- }.inspect
204
- s << "\n | "; s << {
205
- #own_traps: @traps.reject { |t| t.texid == nil }.size, # FIXME
206
- counters: @execution['counters'],
207
- nodes: @execution['nodes'].size,
208
- size: @execution['size']
209
- }.inspect
210
- if @unit.archive
211
- s << "\n | "
212
- s << {
213
- archive_size: @unit.archive[@exid].size
214
- }.inspect
215
- end
216
- s << "\n \\--- ."
217
- s << _c.rs
218
-
219
- puts s.string
220
- end
221
-
222
166
  def on_do_run_exc(e)
223
167
 
224
168
  io = StringIO.new
@@ -24,9 +24,11 @@
24
24
 
25
25
  module Flor
26
26
 
27
- class Tasker
27
+ class Ganger
28
28
 
29
- # NB: tasker configuration entries start with "tsk_"
29
+ # NB: tasker configuration entries start with "gan_"
30
+
31
+ attr_reader :unit
30
32
 
31
33
  def initialize(unit)
32
34
 
@@ -51,6 +53,8 @@ module Flor
51
53
  tconf =
52
54
  ( ! message['routed'] && @unit.loader.tasker(domain, 'tasker')) ||
53
55
  @unit.loader.tasker(domain, tname)
56
+ #
57
+ # TODO `.tasker(domain, 'ganger')`
54
58
 
55
59
  fail ArgumentError.new(
56
60
  "tasker #{tname.inspect} not found"
@@ -115,13 +119,18 @@ module Flor
115
119
  k = tconf['on_task']['class']
116
120
  k = Flor.const_lookup(k)
117
121
 
118
- tasker = k.new(self, tconf)
122
+ ka = k.instance_method(:initialize).arity
123
+
124
+ m =
125
+ message['point'] == 'detask' ?
126
+ :cancel :
127
+ :task
119
128
 
120
129
  r =
121
- if message['point'] == 'detask'
122
- tasker.cancel(message)
123
- else
124
- tasker.task(message)
130
+ if ka == 2
131
+ k.new(self, tconf).send(m, message)
132
+ else # ka == 3
133
+ k.new(self, tconf, message).send(m)
125
134
  end
126
135
 
127
136
  # if the tasker returns something intelligible, use it
@@ -32,17 +32,7 @@ module Flor
32
32
 
33
33
  @unit = unit
34
34
 
35
- @dir = @unit.conf['log_dir'] || 'tmp'
36
- @dir = '.' unless @dir.is_a?(String) && File.exist?(@dir)
37
-
38
- @fname = nil
39
- @file = nil
40
-
41
- @mutex = Mutex.new
42
-
43
- @unit.singleton_class.instance_eval do
44
- define_method(:logger) { @hooker['logger'] }
45
- end
35
+ @out = prepare_out
46
36
 
47
37
  @uni = @unit.identifier
48
38
  end
@@ -51,7 +41,8 @@ module Flor
51
41
 
52
42
  def shutdown
53
43
 
54
- @file.close if @file
44
+ #@file.close if @file
45
+ @out.close
55
46
  end
56
47
 
57
48
  def debug(*m); log(:debug, *m); end
@@ -61,63 +52,55 @@ module Flor
61
52
 
62
53
  def log(level, *elts)
63
54
 
64
- return if [ nil, 'null', false ].include?(@dir)
65
-
66
55
  n = Time.now.utc
67
56
  stp = Flor.tstamp(n)
68
57
 
69
- out =
70
- case @dir
71
- when 'stdout' then $stdout
72
- when 'stderr' then $stderr
73
- else prepare_file(n)
74
- end
75
-
76
58
  lvl = level.to_s.upcase
77
59
  txt = elts.collect(&:to_s).join(' ')
78
60
  err = elts.find { |e| e.is_a?(Exception) }
79
61
 
80
62
  line = "#{stp} #{@uni} #{lvl} #{txt}"
81
63
 
82
- @mutex.synchronize do
83
- if err
84
- sts = ' ' * stp.length
85
- lvs = ' ' * (@uni.length + 1 + lvl.length)
86
- dig = lvl[0, 1] + Digest::MD5.hexdigest(line)[0, 4]
87
- out.puts("#{stp} #{@uni} #{lvl} #{dig} #{txt}")
88
- err.backtrace.each { |lin| out.puts("#{sts} #{lvs} #{dig} #{lin}") }
89
- else
90
- out.puts(line)
91
- end
64
+ if err
65
+ sts = ' ' * stp.length
66
+ lvs = ' ' * (@uni.length + 1 + lvl.length)
67
+ dig = lvl[0, 1] + Digest::MD5.hexdigest(line)[0, 4]
68
+ @out.puts("#{stp} #{@uni} #{lvl} #{dig} #{txt}")
69
+ err.backtrace.each { |lin| @out.puts(" #{dig} #{@uni} #{lin}") }
70
+ else
71
+ @out.puts(line)
92
72
  end
93
73
  end
94
74
 
95
75
  def notify(executor, msg)
96
76
 
77
+ # TODO log to outfile
97
78
  if msg['rewritten'] && @unit.conf['log_tree_rw']
98
79
 
99
80
  Flor.print_compact_tree(
100
81
  msg['rewritten'], msg['nid'],
101
- ind: 6, title: "rewrote #{msg['exid']} #{msg['nid']}")
82
+ ind: 6, title: "rewrote #{msg['exid']} #{msg['nid']}",
83
+ out: @out)
102
84
  Flor.print_compact_tree(
103
85
  msg['tree'], msg['nid'],
104
86
  ind: 6, title: "into #{msg['exid']} #{msg['nid']}",
105
- close: true)
87
+ close: true,
88
+ out: @out)
106
89
  end
107
90
 
108
91
  if @unit.conf['log_msg']
109
92
 
110
- Flor.log_message(executor, msg)
93
+ Flor.log_message(executor, msg, out: @out)
111
94
  end
112
95
 
113
- []
96
+ [] # we're only logging, do not queue further messages
114
97
  end
115
98
 
116
99
  def db_log(level, msg)
117
100
 
118
101
  return unless @unit.conf['log_sto']
119
102
 
120
- _c = Flor.colours
103
+ _c = Flor.colours(out: @out)
121
104
 
122
105
  #m = msg.match(/ (INSERT|UPDATE) .+ (0?[xX]'?[a-fA-F0-9]+'?)/)
123
106
  #msg = msg.sub(m[2], "#{m[2][0, 14]}(...len#{m[2].length})") if m
@@ -126,29 +109,90 @@ module Flor
126
109
  #
127
110
  msg = summarize_blob(msg)
128
111
 
129
- puts "#{_c.blg}sto#{_c.rs} t#{Thread.current.object_id} #{level.upcase} #{msg}"
112
+ @out.puts "#{_c.blg}sto#{_c.rs} t#{Thread.current.object_id} #{level.upcase} #{msg}"
130
113
  end
131
114
 
132
- protected
115
+ def log_run_start(executor)
133
116
 
134
- def prepare_file(t)
117
+ return unless @unit.conf['log_run']
135
118
 
136
- @mutex.synchronize do
119
+ execution = executor.execution
120
+ _c = Flor.colours(out: @out)
121
+ s = StringIO.new
137
122
 
138
- fn = File.join(
139
- @dir,
140
- "#{@unit.conf['env']}_#{t.strftime('%Y-%m-%d')}.log")
123
+ s << _c.dg
124
+ s << " /--- #{_c.lg}run starts#{_c.dg} "
125
+ s << "#{executor.class} #{executor.object_id} #{execution['exid']}"
126
+ s << "\n | "
127
+ s << { thread: Thread.current.object_id }.inspect
128
+ s << "\n | "
129
+ s << {
130
+ counters: execution['counters'],
131
+ nodes: execution['nodes'].size,
132
+ size: execution['size']
133
+ }.inspect
134
+ s << _c.rs
141
135
 
142
- if fn != @fname
143
- @file.close if @file
144
- @file = nil
145
- @fname = fn
146
- end
136
+ @out.puts(s.string)
137
+ end
147
138
 
148
- @file ||= File.open(@fname, 'ab')
139
+ def log_run_end(executor, t0)
140
+
141
+ return unless @unit.conf['log_run']
142
+
143
+ execution = executor.execution
144
+ _c = Flor.colours(out: @out)
145
+ s = StringIO.new
146
+
147
+ s << _c.dg
148
+ s << " | run ends #{self.class} #{self.object_id} #{@exid}"
149
+ s << "\n | "; s << { took: Time.now - t0 }.inspect
150
+ s << "\n | "; s << {
151
+ thread: Thread.current.object_id,
152
+ consumed: executor.consumed.count,
153
+ traps: executor.traps.count,
154
+ }.inspect
155
+ s << "\n | "; s << {
156
+ #own_traps: @traps.reject { |t| t.texid == nil }.size, # FIXME
157
+ counters: execution['counters'],
158
+ nodes: execution['nodes'].size,
159
+ size: execution['size']
160
+ }.inspect
161
+ if @unit.archive
162
+ s << "\n | "
163
+ s << {
164
+ archive_size: @unit.archive[@exid].size
165
+ }.inspect
149
166
  end
167
+ s << "\n \\--- ."
168
+ s << _c.rs
169
+
170
+ @out.puts(s.string)
171
+ end
172
+
173
+ def log_err(executor, message, opts={})
174
+
175
+ return unless @unit.conf['log_err']
176
+
177
+ Flor.print_detail_msg(executor, message, opts.merge(out: @out))
178
+ end
179
+
180
+ def log_src(source, opts, log_opts={})
181
+
182
+ return unless @unit.conf['log_src']
183
+
184
+ Flor.print_src(source, opts, log_opts.merge(out: @out))
185
+ end
186
+
187
+ def log_tree(tree, nid='0', opts={})
188
+
189
+ return unless @unit.conf['log_tree']
190
+
191
+ Flor.print_tree(tree, nid, opts.merge(out: @out))
150
192
  end
151
193
 
194
+ protected
195
+
152
196
  BLOB_CHARS = (('a'..'f').to_a + ('A'..'F').to_a + ('0'..'9').to_a).freeze
153
197
 
154
198
  def summarize_blob(message)
@@ -176,6 +220,77 @@ module Flor
176
220
 
177
221
  message[0..k + 2 + 4] + "(...len#{i - (k + 2 + 1)})" + message[i..-1]
178
222
  end
223
+
224
+ def prepare_out
225
+
226
+ case (o = @unit.conf['log_out'] || 'stdout')
227
+ when false, 'null' then NoOut.new(@unit)
228
+ when true, 'stdout' then StdOut.new(@unit, $stdout)
229
+ when 'stderr' then StdOut.new(@unit, $stderr)
230
+ when /::/ then Flor.const_lookup(o).new(@unit)
231
+ else FileOut.new(@unit, o)
232
+ end
233
+ end
234
+
235
+ class Out
236
+ attr_reader :unit
237
+ def initialize(unit); @unit = unit; end
238
+ def log_colours?; @unit.conf.fetch('log_colours') { :no } == true; end
239
+ def puts(s); end
240
+ def flush; end
241
+ def close; end
242
+ end
243
+
244
+ class NoOut < Out
245
+ def log_colours?; false; end
246
+ end
247
+
248
+ class StdOut < Out
249
+ def initialize(unit, f); super(unit); @f = f; end
250
+ def log_colours?
251
+ lc = @unit.conf.fetch('log_colours') { :no }
252
+ return lc if [ true, false ].include?(lc)
253
+ @f.tty?
254
+ end
255
+ def puts(s); @f.puts(s); end
256
+ def flush; @f.flush; end
257
+ end
258
+
259
+ class FileOut < Out
260
+
261
+ def initialize(unit, dir)
262
+
263
+ super(unit)
264
+ @dir = dir
265
+
266
+ @mutex = Mutex.new
267
+ @file = nil
268
+ @fname = nil
269
+ end
270
+
271
+ def flush; @mutex.synchronize { @file.flush if @file }; end
272
+ def close; @mutex.synchronize { @file.close if @file }; end
273
+
274
+ def puts(s)
275
+ @mutex.synchronize { prepare_file.puts(s) }
276
+ end # TODO tstamp!
277
+
278
+ protected
279
+
280
+ def prepare_file
281
+
282
+ fn = File.join(
283
+ @dir, "#{@unit.env}_#{Time.now.strftime('%Y-%m-%d')}.log")
284
+
285
+ if fn != @fname
286
+ @file.close if @file
287
+ @file = nil
288
+ @fname = fn
289
+ end
290
+
291
+ @file ||= File.open(@fname, 'ab')
292
+ end
293
+ end
179
294
  end
180
295
  end
181
296