flor 1.0.0 → 1.2.1
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 +4 -4
- data/CHANGELOG.md +32 -1
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/lib/flor.rb +2 -1
- data/lib/flor/core/texecutor.rb +26 -1
- data/lib/flor/flor.rb +28 -11
- data/lib/flor/id.rb +4 -1
- data/lib/flor/log.rb +12 -7
- data/lib/flor/punit/c_iterator.rb +1 -1
- data/lib/flor/punit/concurrence.rb +6 -5
- data/lib/flor/punit/{m_ram.rb → m_receive_and_merge.rb} +4 -4
- data/lib/flor/tools/firb.rb +33 -0
- data/lib/flor/tools/shell.rb +12 -3
- data/lib/flor/unit.rb +1 -0
- data/lib/flor/unit/caller.rb +6 -4
- data/lib/flor/unit/caller_jruby.rb +8 -7
- data/lib/flor/unit/executor.rb +18 -13
- data/lib/flor/unit/ganger.rb +3 -0
- data/lib/flor/unit/gangers.rb +125 -0
- data/lib/flor/unit/loader.rb +42 -10
- data/lib/flor/unit/logger.rb +11 -2
- data/lib/flor/unit/models/message.rb +5 -0
- data/lib/flor/unit/models/pointer.rb +20 -1
- data/lib/flor/unit/scheduler.rb +16 -8
- data/lib/flor/unit/storage.rb +54 -46
- data/lib/flor/unit/taskers.rb +68 -0
- data/lib/flor/unit/waiter.rb +20 -16
- data/lib/flor/unit/wlist.rb +9 -0
- metadata +5 -3
data/lib/flor/unit/executor.rb
CHANGED
@@ -109,15 +109,13 @@ module Flor
|
|
109
109
|
rescue Exception => exc
|
110
110
|
|
111
111
|
# TODO eventually, have a dump dir
|
112
|
+
|
112
113
|
fn =
|
113
|
-
[
|
114
|
-
'
|
115
|
-
@unit.conf['env'], @unit.identifier, @exid,
|
116
|
-
'r' + counter('runs').to_s
|
117
|
-
].collect(&:to_s).join('_') + '.dump'
|
114
|
+
[ 'flor', @unit.conf['env'], @unit.identifier, @exid,
|
115
|
+
'r' + counter('runs').to_s ].collect(&:to_s).join('_') + '.dump'
|
118
116
|
|
119
117
|
@unit.logger.error(
|
120
|
-
"#{self.class}#do_run()", exc, "(dumping to #{fn})")
|
118
|
+
"#{self.class}#do_run()", exc, "(dumping to #{fn} ...)")
|
121
119
|
|
122
120
|
File.open(fn, 'wb') do |f|
|
123
121
|
f.puts(Flor.to_pretty_s({
|
@@ -134,19 +132,26 @@ module Flor
|
|
134
132
|
f.puts(on_do_run_exc(exc))
|
135
133
|
end
|
136
134
|
|
135
|
+
@unit.logger.error(
|
136
|
+
"#{self.class}#do_run()", exc, "(dumped to #{fn})")
|
137
|
+
|
137
138
|
#puts on_do_run_exc(exc)
|
138
139
|
# dump notification above
|
139
140
|
end
|
140
141
|
|
141
142
|
def task(message)
|
142
143
|
|
143
|
-
|
144
|
-
|
145
|
-
message
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
144
|
+
if message['routed'] == false
|
145
|
+
|
146
|
+
t = message['tasker']
|
147
|
+
n = node(message['nid'])
|
148
|
+
|
149
|
+
msg = n['heat0'] != t ?
|
150
|
+
"tasker #{t.inspect} not found" :
|
151
|
+
"don't know how to apply #{t.inspect}"
|
152
|
+
|
153
|
+
return error_reply(n, message, msg)
|
154
|
+
end
|
150
155
|
|
151
156
|
@unit.ganger.task(self, message)
|
152
157
|
end
|
data/lib/flor/unit/ganger.rb
CHANGED
@@ -54,6 +54,9 @@ module Flor
|
|
54
54
|
(@unit.loader.tasker(domain, 'ganger', message) ||
|
55
55
|
@unit.loader.tasker(domain, 'tasker', message))) ||
|
56
56
|
@unit.loader.tasker(domain, tname, message)
|
57
|
+
#puts "=" * 80
|
58
|
+
#pp tconf
|
59
|
+
#puts "=" * 80
|
57
60
|
|
58
61
|
fail ArgumentError.new(
|
59
62
|
"tasker #{tname.inspect} not found"
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Flor
|
4
|
+
|
5
|
+
# A ModuleGanger accepts a `module:` conf entry that points to a Ruby
|
6
|
+
# module. The tasker implementations are searched for among the classes
|
7
|
+
# in the given module.
|
8
|
+
#
|
9
|
+
# Among the tasker classes (classes that respond to on_task, on_detask, ...)
|
10
|
+
# it selects the first tasker that matches the tasker name.
|
11
|
+
#
|
12
|
+
class ModuleGanger
|
13
|
+
|
14
|
+
def initialize(service, conf, message)
|
15
|
+
|
16
|
+
@service = service
|
17
|
+
@conf = conf
|
18
|
+
@message = message
|
19
|
+
end
|
20
|
+
|
21
|
+
def task
|
22
|
+
|
23
|
+
tas = @message['tasker']
|
24
|
+
clas = list_tasker_classes
|
25
|
+
cla = clas.find { |c| tasker_name(c) == tas }
|
26
|
+
|
27
|
+
return [ Flor.dup_and_merge(@message, 'routed' => false) ] \
|
28
|
+
unless cla
|
29
|
+
|
30
|
+
call_tasker(cla)
|
31
|
+
end
|
32
|
+
|
33
|
+
alias detask task
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def list_tasker_classes
|
38
|
+
|
39
|
+
mod_name = @conf['module']
|
40
|
+
|
41
|
+
fail ArgumentError.new('ganger module: configuration entry missing') \
|
42
|
+
unless mod_name
|
43
|
+
|
44
|
+
mod = Flor.const_lookup(mod_name) rescue nil
|
45
|
+
|
46
|
+
fail ArgumentError.new("ganger cannot find module #{mod_name.inspect}") \
|
47
|
+
unless mod
|
48
|
+
|
49
|
+
list_classes(mod, [])
|
50
|
+
end
|
51
|
+
|
52
|
+
def list_classes(start, r)
|
53
|
+
|
54
|
+
# place leave classes on top if possible
|
55
|
+
# within a level, sort alphabetically
|
56
|
+
|
57
|
+
clas = start.constants.collect { |co| start.const_get(co) }
|
58
|
+
clas, mods = clas.partition { |c| c.is_a?(Class) }
|
59
|
+
|
60
|
+
mods.each { |m| list_classes(m, r) }
|
61
|
+
r.concat(clas.select { |c| tasker?(c) }.sort_by { |c| c.name })
|
62
|
+
|
63
|
+
r
|
64
|
+
end
|
65
|
+
|
66
|
+
TASKER_METHODS = [
|
67
|
+
:on, :on_message,
|
68
|
+
:task, :on_task,
|
69
|
+
:detask, :on_detask, :cancel, :on_cancel
|
70
|
+
].freeze
|
71
|
+
|
72
|
+
def tasker?(cla)
|
73
|
+
|
74
|
+
return true if (TASKER_METHODS & cla.public_instance_methods).any?
|
75
|
+
return true if (TASKER_METHODS & cla.public_methods).any?
|
76
|
+
false
|
77
|
+
end
|
78
|
+
|
79
|
+
def tasker_name(cla)
|
80
|
+
|
81
|
+
if cla.public_instance_methods.include?(:tasker_name)
|
82
|
+
|
83
|
+
unless cla.respond_to?(:_ganged)
|
84
|
+
class << cla
|
85
|
+
attr_accessor :_ganged
|
86
|
+
end
|
87
|
+
cla._ganged = cla.allocate
|
88
|
+
end
|
89
|
+
|
90
|
+
call_tasker_name(cla._ganged)
|
91
|
+
|
92
|
+
elsif cla.public_methods.include?(:tasker_name)
|
93
|
+
|
94
|
+
call_tasker_name(cla)
|
95
|
+
|
96
|
+
else
|
97
|
+
|
98
|
+
cla.name.split('::').last.gsub(/Tasker\z/, '')
|
99
|
+
.gsub(/([a-z])([A-Z])/) { |_| $1 + '_' + $2.downcase }
|
100
|
+
.gsub(/([A-Z])/) { |c| c.downcase }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def call_tasker_name(o)
|
105
|
+
|
106
|
+
case i = o.method(:tasker_name).arity
|
107
|
+
when 1 then o.tasker_name(@message)
|
108
|
+
when 2 then o.tasker_name(@conf, @message)
|
109
|
+
when 3 then o.tasker_name(@service, @conf, @message)
|
110
|
+
when -1 then o.tasker_name(
|
111
|
+
service: @service, conf: @conf, message: @message)
|
112
|
+
else o.tasker_name
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def call_tasker(c)
|
117
|
+
|
118
|
+
cnf = @conf.merge('class' => c)
|
119
|
+
|
120
|
+
@service.unit.caller
|
121
|
+
.call(@service, cnf, @message)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
data/lib/flor/unit/loader.rb
CHANGED
@@ -46,7 +46,7 @@ module Flor
|
|
46
46
|
.collect { |pa| [ pa, expose_d(pa, {}) ] }
|
47
47
|
.select { |pa, d| Flor.sub_domain?(d, domain) }
|
48
48
|
.sort_by { |pa, d| d.count('.') }
|
49
|
-
.inject({}) { |vars, (pa, _)| vars.merge!(
|
49
|
+
.inject({}) { |vars, (pa, _)| vars.merge!(eval_variables(pa, {})) }
|
50
50
|
end
|
51
51
|
|
52
52
|
#def procedures(path)
|
@@ -87,25 +87,28 @@ module Flor
|
|
87
87
|
.select { |pa| pa.index('/lib/taskers/') }
|
88
88
|
.collect { |pa| [ pa, *expose_dn(pa, {}) ] }
|
89
89
|
.select { |pa, d, n|
|
90
|
-
Flor.sub_domain?([ d, n ]
|
90
|
+
Flor.sub_domain?([ d, n ], domain) ||
|
91
91
|
(n == name && Flor.sub_domain?(d, domain)) }
|
92
92
|
.sort_by { |pa, d, n| d.count('.') }
|
93
93
|
.last
|
94
94
|
|
95
95
|
return nil unless pat
|
96
96
|
|
97
|
-
conf =
|
97
|
+
conf = eval_tasker_conf(pat, message)
|
98
98
|
|
99
99
|
return conf if nam == name
|
100
100
|
|
101
|
-
|
101
|
+
cnf = conf[name]
|
102
102
|
|
103
|
-
return nil unless
|
103
|
+
return nil unless cnf
|
104
104
|
|
105
|
-
|
106
|
-
|
105
|
+
extras = conf.select { |_, v| ! v.is_a?(Hash) }
|
106
|
+
extras['_path'] = pat
|
107
107
|
|
108
|
-
|
108
|
+
(cnf.is_a?(Array) ? cnf : [ cnf ])
|
109
|
+
.each { |h| h.merge!(extras) }
|
110
|
+
|
111
|
+
cnf
|
109
112
|
end
|
110
113
|
|
111
114
|
def hooks(domain)
|
@@ -119,8 +122,8 @@ module Flor
|
|
119
122
|
.select { |pa, d| Flor.sub_domain?(d, domain) }
|
120
123
|
.sort_by { |pa, d| d.count('.') }
|
121
124
|
.collect { |pa, d|
|
122
|
-
|
123
|
-
.each_with_index { |h, i| h['_path'] = pa
|
125
|
+
eval_hook_conf(pa, {})
|
126
|
+
.each_with_index { |h, i| h['_path'] = "#{pa}:#{i}" } }
|
124
127
|
.flatten(1)
|
125
128
|
end
|
126
129
|
|
@@ -247,6 +250,35 @@ module Flor
|
|
247
250
|
end
|
248
251
|
end
|
249
252
|
|
253
|
+
def eval_variables(path, context)
|
254
|
+
eval(path, context)
|
255
|
+
end
|
256
|
+
def eval_tasker_conf(path, context)
|
257
|
+
eval(path, context)
|
258
|
+
end
|
259
|
+
# TODO like in eval_hook_conf, reject fautly tasker confs...
|
260
|
+
# TODO like in eval_hook_conf, reject fautly variables...
|
261
|
+
|
262
|
+
def eval_hook_conf(path, context)
|
263
|
+
|
264
|
+
a = eval(path, context)
|
265
|
+
|
266
|
+
fail ArgumentError.new(
|
267
|
+
"hook conf at #{path} must be an array of hashes"
|
268
|
+
) unless a.is_a?(Array)
|
269
|
+
|
270
|
+
a.each do |e|
|
271
|
+
fail ArgumentError.new(
|
272
|
+
"hook conf at #{path} has non-hash entry #{e.inspect}"
|
273
|
+
) unless e.is_a?(Hash)
|
274
|
+
fail ArgumentError.new(
|
275
|
+
"hook conf at #{path} has incorrect point #{e['point'].inspect}"
|
276
|
+
) unless e['point'].is_a?(String)
|
277
|
+
end
|
278
|
+
|
279
|
+
a
|
280
|
+
end
|
281
|
+
|
250
282
|
def eval(path, context)
|
251
283
|
|
252
284
|
ext =
|
data/lib/flor/unit/logger.rb
CHANGED
@@ -71,7 +71,8 @@ module Flor
|
|
71
71
|
dbi = ' ' + dbi if dbi.length > 0
|
72
72
|
|
73
73
|
txt = elts.collect(&:to_s).join(' ')
|
74
|
-
|
74
|
+
|
75
|
+
err = find_err(elts)
|
75
76
|
|
76
77
|
head = "#{stp} #{@uni}#{dbi} #{lvl} "
|
77
78
|
|
@@ -198,7 +199,8 @@ module Flor
|
|
198
199
|
|
199
200
|
return unless @unit.conf['log_err']
|
200
201
|
|
201
|
-
|
202
|
+
s = Flor.msg_to_detail_s(executor, message, opts.merge(flag: true))
|
203
|
+
@out.puts(s) if s
|
202
204
|
end
|
203
205
|
|
204
206
|
def log_src(source, opts, log_opts={})
|
@@ -245,6 +247,13 @@ module Flor
|
|
245
247
|
message[0..k + 2 + 4] + "(...len#{i - (k + 2 + 1)})" + message[i..-1]
|
246
248
|
end
|
247
249
|
|
250
|
+
def find_err(elts)
|
251
|
+
|
252
|
+
elts.find { |e| e.is_a?(Exception) } ||
|
253
|
+
(defined?(Java) &&
|
254
|
+
elts.find { |e| e.class.ancestors.include?(Java::JavaLang::Error) })
|
255
|
+
end
|
256
|
+
|
248
257
|
class Out
|
249
258
|
|
250
259
|
attr_reader :unit
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
|
3
4
|
module Flor
|
4
5
|
|
5
6
|
class Message < FlorModel
|
@@ -19,6 +20,10 @@ module Flor
|
|
19
20
|
#
|
20
21
|
# index :exid
|
21
22
|
#end
|
23
|
+
|
24
|
+
def nid; data['nid']; end
|
25
|
+
def tasker; data['tasker']; end
|
26
|
+
alias payload data
|
22
27
|
end
|
23
28
|
end
|
24
29
|
|
@@ -30,7 +30,7 @@ module Flor
|
|
30
30
|
#end
|
31
31
|
|
32
32
|
# If the pointer is a "var" pointer, returns the full value
|
33
|
-
# for the variable, as
|
33
|
+
# for the variable, as found in the execution's node "0".
|
34
34
|
#
|
35
35
|
def full_value
|
36
36
|
|
@@ -38,6 +38,25 @@ module Flor
|
|
38
38
|
|
39
39
|
node['vars'][name]
|
40
40
|
end
|
41
|
+
|
42
|
+
def attd
|
43
|
+
|
44
|
+
data['atts'].inject({}) { |h, (k, v)| h[k] = v if k; h }
|
45
|
+
|
46
|
+
rescue; []
|
47
|
+
end
|
48
|
+
|
49
|
+
def attl
|
50
|
+
|
51
|
+
data['atts'].inject([]) { |a, (k, v)| a << v if k == nil; a }
|
52
|
+
|
53
|
+
rescue; []
|
54
|
+
end
|
55
|
+
|
56
|
+
def att_texts
|
57
|
+
|
58
|
+
attl.select { |e| e.is_a?(String) }
|
59
|
+
end
|
41
60
|
end
|
42
61
|
end
|
43
62
|
|
data/lib/flor/unit/scheduler.rb
CHANGED
@@ -138,11 +138,7 @@ module Flor
|
|
138
138
|
|
139
139
|
# TODO heartbeat, every x minutes, when idle, log something
|
140
140
|
|
141
|
-
|
142
|
-
"database not ready, " +
|
143
|
-
"db ver: #{@storage.db_version.inspect}, " +
|
144
|
-
"mig ver: #{@storage.migration_version}"
|
145
|
-
) if !! @conf['sto_migration_check'] && @storage.ready?
|
141
|
+
check_migration_version
|
146
142
|
|
147
143
|
@thread_status = :running
|
148
144
|
|
@@ -162,6 +158,15 @@ module Flor
|
|
162
158
|
self
|
163
159
|
end
|
164
160
|
|
161
|
+
def check_migration_version
|
162
|
+
|
163
|
+
fail(
|
164
|
+
"database not ready, " +
|
165
|
+
"db ver: #{@storage.db_version.inspect}, " +
|
166
|
+
"mig ver: #{@storage.migration_version}"
|
167
|
+
) if !! @conf['sto_migration_check'] && @storage.ready?
|
168
|
+
end
|
169
|
+
|
165
170
|
def stop
|
166
171
|
|
167
172
|
@thread_status = :stop
|
@@ -227,6 +232,9 @@ module Flor
|
|
227
232
|
@last_queued_message_id =
|
228
233
|
@storage.put_message(message)
|
229
234
|
|
235
|
+
# Nota bene:
|
236
|
+
# the #wait method is added to the Scheduler by Flor::WaitList
|
237
|
+
|
230
238
|
if opts[:wait]
|
231
239
|
wait(message['exid'], opts)
|
232
240
|
else
|
@@ -587,7 +595,7 @@ module Flor
|
|
587
595
|
|
588
596
|
rescue Exception => ex
|
589
597
|
|
590
|
-
puts
|
598
|
+
puts(on_start_exc(ex))
|
591
599
|
end
|
592
600
|
|
593
601
|
def prepare_message(point, args)
|
@@ -675,9 +683,9 @@ module Flor
|
|
675
683
|
def should_wake_up?
|
676
684
|
|
677
685
|
return true if @wake_up
|
678
|
-
return true if Time.now - @reloaded_at >= reload_after
|
686
|
+
return true if (Time.now - @reloaded_at) >= reload_after
|
679
687
|
|
680
|
-
@next_time && @next_time <= Flor.
|
688
|
+
@next_time && (@next_time <= Flor.tstam)
|
681
689
|
end
|
682
690
|
|
683
691
|
def unreserve_messages
|
data/lib/flor/unit/storage.rb
CHANGED
@@ -7,6 +7,14 @@ module Flor
|
|
7
7
|
|
8
8
|
class Storage
|
9
9
|
|
10
|
+
MESSAGE_COLUMNS = [
|
11
|
+
:domain, :exid, :point, :content,
|
12
|
+
:status, :ctime, :mtime, :cunit, :munit
|
13
|
+
].freeze
|
14
|
+
POINTER_COLUMNS = [
|
15
|
+
:domain, :exid, :nid, :type, :name, :value, :ctime, :cunit
|
16
|
+
].freeze
|
17
|
+
|
10
18
|
attr_reader :unit, :db, :models
|
11
19
|
|
12
20
|
attr_reader :mutex
|
@@ -352,8 +360,7 @@ module Flor
|
|
352
360
|
|
353
361
|
@db[:flor_messages]
|
354
362
|
.import(
|
355
|
-
|
356
|
-
:status, :ctime, :mtime, :cunit, :munit ],
|
363
|
+
MESSAGE_COLUMNS,
|
357
364
|
unstored.map { |m|
|
358
365
|
[ Flor.domain(m['exid']), m['exid'], m['point'], to_blob(m),
|
359
366
|
'created', n, n, u, u ] }) \
|
@@ -517,25 +524,6 @@ module Flor
|
|
517
524
|
end
|
518
525
|
end
|
519
526
|
|
520
|
-
def put_task_pointer(msg, tname, tconf)
|
521
|
-
|
522
|
-
exid = msg['exid']
|
523
|
-
dom = Flor.domain(exid)
|
524
|
-
|
525
|
-
synchronize do
|
526
|
-
|
527
|
-
@db[:flor_pointers]
|
528
|
-
.insert(
|
529
|
-
domain: dom,
|
530
|
-
exid: exid,
|
531
|
-
nid: msg['nid'],
|
532
|
-
type: 'tasker',
|
533
|
-
name: tname,
|
534
|
-
ctime: Flor.tstamp,
|
535
|
-
cunit: @unit.identifier)
|
536
|
-
end
|
537
|
-
end
|
538
|
-
|
539
527
|
def fetch_next_time
|
540
528
|
|
541
529
|
t =
|
@@ -598,14 +586,13 @@ module Flor
|
|
598
586
|
|
599
587
|
@db[:flor_messages]
|
600
588
|
.where(
|
601
|
-
id: messages.collect { |m| m['mid'] }.compact)
|
589
|
+
id: messages.collect { |m| m['mid'] }.uniq.compact)
|
602
590
|
.update(
|
603
591
|
status: 'consumed', mtime: n, munit: u)
|
604
592
|
|
605
593
|
@db[:flor_messages]
|
606
594
|
.import(
|
607
|
-
|
608
|
-
:status, :ctime, :mtime, :cunit, :munit ],
|
595
|
+
MESSAGE_COLUMNS,
|
609
596
|
messages
|
610
597
|
.select { |m|
|
611
598
|
! m['mid'] && POINTS_TO_ARCHIVE.include?(m['point']) }
|
@@ -621,19 +608,16 @@ module Flor
|
|
621
608
|
|
622
609
|
@db[:flor_messages]
|
623
610
|
.where(
|
624
|
-
id: messages.collect { |m| m['mid'] }.compact)
|
611
|
+
id: messages.collect { |m| m['mid'] }.uniq.compact)
|
625
612
|
.delete
|
626
613
|
end
|
627
614
|
end
|
628
615
|
|
629
616
|
def load_timers
|
630
617
|
|
631
|
-
now = Flor.tstamp
|
632
|
-
no = now[0, now.rindex('.')]
|
633
|
-
|
634
618
|
timers
|
635
619
|
.where(status: 'active')
|
636
|
-
.where { ntime <=
|
620
|
+
.where { ntime <= Flor.tstam }
|
637
621
|
.order(:ntime)
|
638
622
|
.all
|
639
623
|
|
@@ -703,9 +687,9 @@ module Flor
|
|
703
687
|
|
704
688
|
def update_pointers(exe, status, now)
|
705
689
|
|
706
|
-
# Q
|
707
|
-
#
|
708
|
-
#
|
690
|
+
# Q Should we archive old pointers?
|
691
|
+
# A Well, it might be better to only archive the execution and leave
|
692
|
+
# in there enough information...
|
709
693
|
|
710
694
|
exid = exe['exid']
|
711
695
|
|
@@ -731,23 +715,25 @@ module Flor
|
|
731
715
|
|
732
716
|
ts = node['tags']
|
733
717
|
ts.each { |t|
|
734
|
-
a << [ dom, exid, nid, 'tag', t, nil, now, u ] } if ts
|
718
|
+
a << [ dom, exid, nid, 'tag', t, nil, now, u, nil ] } if ts
|
735
719
|
|
736
720
|
vs = nid == '0' ? node['vars'] : nil
|
737
721
|
vs.each { |k, v|
|
738
722
|
case v; when Numeric, String, TrueClass, FalseClass, NilClass
|
739
|
-
a << [ dom, exid, '0', 'var', k, v.to_s, now, u ]
|
723
|
+
a << [ dom, exid, '0', 'var', k, v.to_s, now, u, nil ]
|
740
724
|
when Array, Hash
|
741
725
|
s = '(array)'; s = '(object)' if v.is_a?(Hash)
|
742
|
-
a << [ dom, exid, '0', 'var', k, s, now, u ]
|
726
|
+
a << [ dom, exid, '0', 'var', k, s, now, u, nil ]
|
743
727
|
else
|
744
|
-
a << [ dom, exid, '0', 'var', k, nil, now, u ]
|
728
|
+
a << [ dom, exid, '0', 'var', k, nil, now, u, nil ]
|
745
729
|
end } if vs
|
746
730
|
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
731
|
+
if ta = node['task']
|
732
|
+
tasker = ta['tasker']
|
733
|
+
name = ta['name']
|
734
|
+
content = { message: node['message'], atts: node['atts'] }
|
735
|
+
a << [ dom, exid, nid, 'tasker', tasker, name, now, u, content ]
|
736
|
+
end
|
751
737
|
|
752
738
|
a }
|
753
739
|
|
@@ -755,17 +741,35 @@ module Flor
|
|
755
741
|
.where(exid: exid)
|
756
742
|
.select(:nid, :type, :name)
|
757
743
|
.all
|
758
|
-
pointers.reject! { |_, _, ni, ty, na, _, _, _|
|
744
|
+
pointers.reject! { |_, _, ni, ty, na, _, _, _, _|
|
759
745
|
cps.find { |cp| cp[:nid] == ni && cp[:type] == ty && cp[:name] == na } }
|
760
746
|
#
|
761
747
|
# don't insert when already inserted
|
762
748
|
|
749
|
+
if pointer_columns.include?(:content)
|
750
|
+
pointers.each { |ptr|
|
751
|
+
c = ptr[8]; ptr[8] = to_blob(c) if c }
|
752
|
+
else
|
753
|
+
pointers.each { |ptr|
|
754
|
+
ptr.pop }
|
755
|
+
end
|
756
|
+
|
763
757
|
@db[:flor_pointers]
|
764
758
|
.import(
|
765
|
-
|
759
|
+
pointer_columns,
|
766
760
|
pointers)
|
767
761
|
end
|
768
762
|
|
763
|
+
def pointer_columns
|
764
|
+
|
765
|
+
@pointer_columns ||=
|
766
|
+
if @db[:flor_pointers].columns.include?(:content)
|
767
|
+
POINTER_COLUMNS + [ :content ]
|
768
|
+
else
|
769
|
+
POINTER_COLUMNS
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
769
773
|
def determine_type_and_schedule(message)
|
770
774
|
|
771
775
|
t, s = message['type'], message['string']
|
@@ -822,8 +826,9 @@ module Flor
|
|
822
826
|
fail ArgumentError.new("no 'sto_uri' conf, cannot connect to db") \
|
823
827
|
unless uri
|
824
828
|
|
825
|
-
|
826
|
-
|
829
|
+
return Kernel.const_get(uri) \
|
830
|
+
if uri.is_a?(String) && uri.match(/\A[A-Z]+\z/)
|
831
|
+
# for cases where uri == 'DB'
|
827
832
|
|
828
833
|
Sequel.connect(uri)
|
829
834
|
end
|
@@ -844,8 +849,11 @@ module Flor
|
|
844
849
|
# NB: -1 means "check at every use"
|
845
850
|
end
|
846
851
|
|
847
|
-
@
|
848
|
-
|
852
|
+
if @unit.conf['sto_db_logger'] != false
|
853
|
+
|
854
|
+
@db_logger = DbLogger.new(@unit)
|
855
|
+
@db.loggers << @db_logger
|
856
|
+
end
|
849
857
|
end
|
850
858
|
|
851
859
|
class << self
|