flor 0.17.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +48 -0
  3. data/CREDITS.md +1 -0
  4. data/LICENSE.txt +1 -1
  5. data/Makefile +1 -1
  6. data/README.md +34 -2
  7. data/flor.gemspec +8 -9
  8. data/lib/flor.rb +3 -2
  9. data/lib/flor/colours.rb +5 -3
  10. data/lib/flor/conf.rb +1 -0
  11. data/lib/flor/core.rb +9 -8
  12. data/lib/flor/core/executor.rb +25 -22
  13. data/lib/flor/core/node.rb +1 -13
  14. data/lib/flor/core/procedure.rb +57 -12
  15. data/lib/flor/core/texecutor.rb +35 -3
  16. data/lib/flor/djan.rb +1 -0
  17. data/lib/flor/errors.rb +1 -0
  18. data/lib/flor/flor.rb +173 -29
  19. data/lib/flor/id.rb +5 -1
  20. data/lib/flor/log.rb +20 -8
  21. data/lib/flor/migrations/0001_tables.rb +1 -0
  22. data/lib/flor/migrations/0002_cunit_and_munit.rb +1 -0
  23. data/lib/flor/migrations/0003_timer_onid_bnid.rb +1 -0
  24. data/lib/flor/migrations/0004_trap_bnid.rb +1 -0
  25. data/lib/flor/migrations/0005_pointer_content.rb +1 -0
  26. data/lib/flor/parser.rb +19 -11
  27. data/lib/flor/pcore/_apply.rb +1 -0
  28. data/lib/flor/pcore/_arr.rb +1 -0
  29. data/lib/flor/pcore/_atom.rb +1 -0
  30. data/lib/flor/pcore/_att.rb +1 -0
  31. data/lib/flor/pcore/_coll.rb +1 -0
  32. data/lib/flor/pcore/_dmute.rb +5 -1
  33. data/lib/flor/pcore/_dol.rb +1 -0
  34. data/lib/flor/pcore/_dqs.rb +1 -0
  35. data/lib/flor/pcore/_dump.rb +1 -0
  36. data/lib/flor/pcore/_err.rb +1 -0
  37. data/lib/flor/pcore/_head.rb +1 -0
  38. data/lib/flor/pcore/_obj.rb +1 -0
  39. data/lib/flor/pcore/_pat_.rb +1 -0
  40. data/lib/flor/pcore/_pat_arr.rb +1 -0
  41. data/lib/flor/pcore/_pat_guard.rb +1 -0
  42. data/lib/flor/pcore/_pat_obj.rb +1 -0
  43. data/lib/flor/pcore/_pat_or.rb +1 -0
  44. data/lib/flor/pcore/_pat_regex.rb +1 -0
  45. data/lib/flor/pcore/_ref.rb +1 -0
  46. data/lib/flor/pcore/_rxs.rb +1 -0
  47. data/lib/flor/pcore/_skip.rb +1 -0
  48. data/lib/flor/pcore/_val.rb +1 -0
  49. data/lib/flor/pcore/all.rb +1 -0
  50. data/lib/flor/pcore/andor.rb +1 -0
  51. data/lib/flor/pcore/any.rb +1 -0
  52. data/lib/flor/pcore/apply.rb +1 -0
  53. data/lib/flor/pcore/arith.rb +1 -0
  54. data/lib/flor/pcore/array_qmark.rb +1 -0
  55. data/lib/flor/pcore/break.rb +13 -1
  56. data/lib/flor/pcore/case.rb +1 -0
  57. data/lib/flor/pcore/cmp.rb +1 -0
  58. data/lib/flor/pcore/collect.rb +2 -1
  59. data/lib/flor/pcore/cond.rb +1 -0
  60. data/lib/flor/pcore/cursor.rb +45 -3
  61. data/lib/flor/pcore/define.rb +1 -0
  62. data/lib/flor/pcore/detect.rb +1 -0
  63. data/lib/flor/pcore/do_return.rb +1 -0
  64. data/lib/flor/pcore/each.rb +1 -0
  65. data/lib/flor/pcore/echo.rb +1 -0
  66. data/lib/flor/pcore/empty.rb +1 -0
  67. data/lib/flor/pcore/fail.rb +1 -0
  68. data/lib/flor/pcore/filter.rb +1 -0
  69. data/lib/flor/pcore/find.rb +1 -0
  70. data/lib/flor/pcore/flatten.rb +1 -0
  71. data/lib/flor/pcore/for_each.rb +1 -0
  72. data/lib/flor/pcore/if.rb +1 -0
  73. data/lib/flor/pcore/includes.rb +1 -0
  74. data/lib/flor/pcore/inject.rb +1 -0
  75. data/lib/flor/pcore/iterator.rb +1 -0
  76. data/lib/flor/pcore/keys.rb +1 -0
  77. data/lib/flor/pcore/length.rb +1 -0
  78. data/lib/flor/pcore/loop.rb +1 -0
  79. data/lib/flor/pcore/map.rb +1 -0
  80. data/lib/flor/pcore/match.rb +1 -0
  81. data/lib/flor/pcore/matchr.rb +1 -0
  82. data/lib/flor/pcore/max.rb +1 -0
  83. data/lib/flor/pcore/merge.rb +1 -0
  84. data/lib/flor/pcore/move.rb +1 -0
  85. data/lib/flor/pcore/noeval.rb +1 -0
  86. data/lib/flor/pcore/noret.rb +1 -0
  87. data/lib/flor/pcore/not.rb +1 -0
  88. data/lib/flor/pcore/on.rb +34 -9
  89. data/lib/flor/pcore/on_cancel.rb +1 -0
  90. data/lib/flor/pcore/on_error.rb +1 -0
  91. data/lib/flor/pcore/push.rb +1 -0
  92. data/lib/flor/pcore/rand.rb +1 -0
  93. data/lib/flor/pcore/range.rb +1 -0
  94. data/lib/flor/pcore/reduce.rb +1 -0
  95. data/lib/flor/pcore/return.rb +1 -0
  96. data/lib/flor/pcore/reverse.rb +1 -0
  97. data/lib/flor/pcore/select.rb +1 -0
  98. data/lib/flor/pcore/sequence.rb +49 -0
  99. data/lib/flor/pcore/set.rb +1 -0
  100. data/lib/flor/pcore/shuffle.rb +1 -0
  101. data/lib/flor/pcore/slice.rb +1 -0
  102. data/lib/flor/pcore/sort.rb +1 -0
  103. data/lib/flor/pcore/sort_by.rb +1 -0
  104. data/lib/flor/pcore/split.rb +1 -0
  105. data/lib/flor/pcore/stall.rb +1 -0
  106. data/lib/flor/pcore/strings.rb +1 -0
  107. data/lib/flor/pcore/timestamp.rb +1 -0
  108. data/lib/flor/pcore/to_array.rb +1 -0
  109. data/lib/flor/pcore/twig.rb +1 -0
  110. data/lib/flor/pcore/type_of.rb +1 -0
  111. data/lib/flor/pcore/until.rb +1 -0
  112. data/lib/flor/punit/abort.rb +50 -0
  113. data/lib/flor/punit/c_collect.rb +1 -0
  114. data/lib/flor/punit/c_each.rb +19 -0
  115. data/lib/flor/punit/c_for_each.rb +2 -1
  116. data/lib/flor/punit/c_iterator.rb +2 -1
  117. data/lib/flor/punit/c_map.rb +1 -0
  118. data/lib/flor/punit/cancel.rb +10 -1
  119. data/lib/flor/punit/concurrence.rb +7 -5
  120. data/lib/flor/punit/cron.rb +1 -0
  121. data/lib/flor/punit/do_trap.rb +1 -0
  122. data/lib/flor/punit/every.rb +1 -0
  123. data/lib/flor/punit/graft.rb +1 -0
  124. data/lib/flor/punit/{m_ram.rb → m_receive_and_merge.rb} +5 -4
  125. data/lib/flor/punit/on_timeout.rb +1 -0
  126. data/lib/flor/punit/part.rb +1 -0
  127. data/lib/flor/punit/schedule.rb +1 -0
  128. data/lib/flor/punit/signal.rb +30 -5
  129. data/lib/flor/punit/sleep.rb +1 -0
  130. data/lib/flor/punit/task.rb +9 -2
  131. data/lib/flor/punit/trace.rb +1 -0
  132. data/lib/flor/punit/trap.rb +41 -1
  133. data/lib/flor/to_string.rb +1 -0
  134. data/lib/flor/tools/env.rb +1 -0
  135. data/lib/flor/tools/firb.rb +33 -0
  136. data/lib/flor/tools/shell.rb +13 -3
  137. data/lib/flor/tools/shell_out.rb +1 -0
  138. data/lib/flor/tt.rb +98 -0
  139. data/lib/flor/unit.rb +3 -0
  140. data/lib/flor/unit/caller.rb +158 -23
  141. data/lib/flor/unit/caller_jruby.rb +133 -0
  142. data/lib/flor/unit/dump.rb +36 -0
  143. data/lib/flor/unit/executor.rb +28 -18
  144. data/lib/flor/unit/ganger.rb +30 -18
  145. data/lib/flor/unit/gangers.rb +125 -0
  146. data/lib/flor/unit/hloader.rb +34 -7
  147. data/lib/flor/unit/hook.rb +3 -0
  148. data/lib/flor/unit/hooker.rb +32 -15
  149. data/lib/flor/unit/journal.rb +23 -0
  150. data/lib/flor/unit/loader.rb +142 -15
  151. data/lib/flor/unit/logger.rb +35 -7
  152. data/lib/flor/unit/models.rb +48 -10
  153. data/lib/flor/unit/models/execution.rb +51 -0
  154. data/lib/flor/unit/models/message.rb +6 -0
  155. data/lib/flor/unit/models/pointer.rb +1 -0
  156. data/lib/flor/unit/models/timer.rb +1 -0
  157. data/lib/flor/unit/models/trace.rb +1 -0
  158. data/lib/flor/unit/models/trap.rb +15 -6
  159. data/lib/flor/unit/scheduler.rb +211 -61
  160. data/lib/flor/unit/spooler.rb +1 -0
  161. data/lib/flor/unit/storage.rb +117 -73
  162. data/lib/flor/unit/taskers.rb +115 -1
  163. data/lib/flor/unit/waiter.rb +22 -17
  164. data/lib/flor/unit/wlist.rb +19 -8
  165. metadata +26 -45
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flor
4
+
5
+ class << self
6
+
7
+ # See Scheduler#dump for the details
8
+ #
9
+ def dump(db_or_unit_or_uri, io=nil, opts=nil, &block)
10
+
11
+ derive_unit(db_or_unit_or_uri)
12
+ .dump(io, opts, &block)
13
+ end
14
+
15
+ # See Scheduler#load for the details
16
+ #
17
+ def load(db_or_unit_or_uri, string_or_io, opts={}, &block)
18
+
19
+ derive_unit(db_or_unit_or_uri)
20
+ .load(string_or_io, opts, &block)
21
+ end
22
+
23
+ protected
24
+
25
+ def derive_unit(db_or_unit_or_uri)
26
+
27
+ case o = db_or_unit_or_uri
28
+ when Flor::Unit then o
29
+ when Sequel::Database then Flor::Unit.new(sto_db: o)
30
+ when String then Flor::Unit.new(sto_uri: o)
31
+ else fail ArgumentError.new("cannot derive flor Unit out of #{o.inspect}")
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -108,15 +109,13 @@ module Flor
108
109
  rescue Exception => exc
109
110
 
110
111
  # TODO eventually, have a dump dir
112
+
111
113
  fn =
112
- [
113
- 'flor',
114
- @unit.conf['env'], @unit.identifier, @exid,
115
- 'r' + counter('runs').to_s
116
- ].collect(&:to_s).join('_') + '.dump'
114
+ [ 'flor', @unit.conf['env'], @unit.identifier, @exid,
115
+ 'r' + counter('runs').to_s ].collect(&:to_s).join('_') + '.dump'
117
116
 
118
117
  @unit.logger.error(
119
- "#{self.class}#do_run()", exc, "(dumping to #{fn})")
118
+ "#{self.class}#do_run()", exc, "(dumping to #{fn} ...)")
120
119
 
121
120
  File.open(fn, 'wb') do |f|
122
121
  f.puts(Flor.to_pretty_s({
@@ -133,19 +132,26 @@ module Flor
133
132
  f.puts(on_do_run_exc(exc))
134
133
  end
135
134
 
135
+ @unit.logger.error(
136
+ "#{self.class}#do_run()", exc, "(dumped to #{fn})")
137
+
136
138
  #puts on_do_run_exc(exc)
137
139
  # dump notification above
138
140
  end
139
141
 
140
142
  def task(message)
141
143
 
142
- return error_reply(
143
- node(message['nid']),
144
- message,
145
- "don't know how to apply #{message['tasker'].inspect}"
146
- ) if message['routed'] == false
147
- #
148
- # use an error message similar to what the core executor would emit
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
149
155
 
150
156
  @unit.ganger.task(self, message)
151
157
  end
@@ -153,11 +159,15 @@ module Flor
153
159
 
154
160
  def return(message)
155
161
 
156
- [ { 'point' => 'receive',
157
- 'exid' => message['exid'],
158
- 'nid' => message['nid'],
159
- 'payload' => message['payload'],
160
- 'tasker' => message['tasker'] } ]
162
+ n = @execution['nodes'][message['nid']] || {}
163
+ m = n['message'] || {}
164
+ c = m['cause']
165
+
166
+ rm = message.dup
167
+ rm['point'] = 'receive'
168
+ rm['cause'] = c if c # preserve 'cause' for routing
169
+
170
+ [ rm ]
161
171
  end
162
172
 
163
173
  def schedule(message)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -22,6 +23,12 @@ module Flor
22
23
  def shutdown
23
24
  end
24
25
 
26
+ # Used by flor when it looks up for a variable and finds nothing.
27
+ # The last step is to ask the ganger if it knows about a tasker under
28
+ # the given (domain and) name.
29
+ #
30
+ # If it returns true, flor knows there is a tasker under that name.
31
+ #
25
32
  def has_tasker?(exid, name)
26
33
 
27
34
  #return false if RESERVED_NAMES.include?(name)
@@ -34,6 +41,9 @@ module Flor
34
41
  @unit.loader.tasker(d, name))
35
42
  end
36
43
 
44
+ # Called by Flor::Scheduler. The ganger then has to hand the task
45
+ # (the message) to the proper tasker.
46
+ #
37
47
  def task(executor, message)
38
48
 
39
49
  domain = message['exid'].split('-', 2).first
@@ -44,25 +54,31 @@ module Flor
44
54
  (@unit.loader.tasker(domain, 'ganger', message) ||
45
55
  @unit.loader.tasker(domain, 'tasker', message))) ||
46
56
  @unit.loader.tasker(domain, tname, message)
57
+ #puts "=" * 80
58
+ #pp tconf
59
+ #puts "=" * 80
47
60
 
48
61
  fail ArgumentError.new(
49
62
  "tasker #{tname.inspect} not found"
50
63
  ) unless tconf
51
64
 
52
65
  if tconf.is_a?(Array)
53
- tconf =
54
- tconf.find { |h| h['point'] == message['point'] } ||
55
- tconf.find { |h| h['point'] == nil }
56
- tconf ||=
57
- tconf.find { |h| h['point'] == 'cancel' } \
58
- if message['point'] == 'detask'
66
+
67
+ points = [ nil, message['point'] ]
68
+ points << 'detask' if points.include?('cancel')
69
+
70
+ tconf = tconf.find { |h| points.include?(h['point']) }
59
71
  end
60
72
 
73
+ fail ArgumentError.new(
74
+ "tconf #{tconf.inspect} not a hash"
75
+ ) unless tconf.is_a?(Hash)
76
+
61
77
  message['tconf'] = tconf unless tconf['include_tconf'] == false
62
78
 
63
79
  message['vars'] = gather_vars(executor, tconf, message)
64
80
 
65
- m = dup_message(message)
81
+ m = Flor.dup_message(message)
66
82
  #
67
83
  # the tasker gets a copy of the message (and it can play with it
68
84
  # to its heart content), meanwhile the message is handed to the
@@ -74,6 +90,9 @@ module Flor
74
90
  # especially if it's a domain tasker
75
91
  end
76
92
 
93
+ # Called by the tasker implementations when they're done with a task
94
+ # and want to hand it back to flor. It might be a failure message.
95
+ #
77
96
  def return(message)
78
97
 
79
98
  @unit.return(message)
@@ -81,17 +100,6 @@ module Flor
81
100
 
82
101
  protected
83
102
 
84
- def dup_message(m)
85
-
86
- tc = m.delete('tconf')
87
- m1 = Flor.dup(m)
88
- m1['tconf'] = tc.inject({}) { |h, (k, v)|
89
- h[k] = k == 'class' ? v : Flor.dup(v); h } \
90
- if tc
91
-
92
- m1
93
- end
94
-
95
103
  def var_match(k, filter)
96
104
 
97
105
  filter.each { |f| return true if (f.is_a?(String) ? k == f : f.match(k)) }
@@ -120,6 +128,10 @@ module Flor
120
128
  }.compact
121
129
  end
122
130
 
131
+ # By default, taskers don't see the flor variables in the execution.
132
+ # If 'include_vars' or 'exclude_vars' is present in the configuration
133
+ # of the tasker, some or all of the variables are passed.
134
+ #
123
135
  def gather_vars(executor, tconf, message)
124
136
 
125
137
  # try to return before a potentially costly call to executor.vars(nid)
@@ -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
+
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
4
5
  # A loader which keeps everything in a Hash, while the traditional/default
5
6
  # Flor::Loader reads from a file tree.
6
7
  #
7
- class HashLoader
8
+ class HashLoader < CoreLoader
8
9
 
9
10
  # NB: tasker configuration entries start with "loa_", like for Flor::Loader
10
11
 
@@ -27,9 +28,6 @@ module Flor
27
28
  self.environment = (@unit.conf['lod_environment'] || {})
28
29
  end
29
30
 
30
- def shutdown
31
- end
32
-
33
31
  HCATS = {
34
32
  'v' => 'variables',
35
33
  'var' => 'variables',
@@ -53,9 +51,14 @@ module Flor
53
51
  path = path.to_s
54
52
  path = path + '.' if c == 'hooks' && path.length > 0 && path[-1, 1] != '.'
55
53
 
56
- value = block ?
57
- block_to_class(c, block) :
58
- Flor.to_string_keyed_hash(value)
54
+ value =
55
+ if block
56
+ block_to_class(c, block)
57
+ elsif value.is_a?(Proc)
58
+ block_to_class(c, value)
59
+ else
60
+ Flor.to_string_keyed_hash(value)
61
+ end
59
62
 
60
63
  e = (@environment[c] ||= [])
61
64
  e << [ *split(path), value ]
@@ -132,6 +135,30 @@ module Flor
132
135
  .collect { |h| Flor::Hook.new(@unit, exid, h) }
133
136
  end
134
137
 
138
+ def domains(start=nil)
139
+
140
+ start ||= ''
141
+
142
+ @environment.values
143
+ .flatten(1)
144
+ .collect { |x| x.first }
145
+ .select { |dm| dm && dm.length > 0 }
146
+ .select { |dm| Flor.sub_domain?(start, dm) }
147
+ .uniq
148
+ .sort
149
+ end
150
+
151
+ def definitions(start=nil)
152
+
153
+ start ||= ''
154
+
155
+ @environment.values
156
+ .flatten(1)
157
+ .collect { |x| x[0, 2].join('.') }
158
+ .select { |fl| Flor.sub_domain?(start, fl) }
159
+ .sort
160
+ end
161
+
135
162
  protected
136
163
 
137
164
  def recompose(h)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -14,6 +15,8 @@ module Flor
14
15
 
15
16
  def to_hook
16
17
 
18
+ @unit.loader.require(@h)
19
+
17
20
  if @h['class']
18
21
  class_to_hook
19
22
  elsif @h['instance']
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -5,6 +6,22 @@ module Flor
5
6
 
6
7
  # NB: logger configuration entries start with "hok_"
7
8
 
9
+ attr_reader :hooks
10
+
11
+ KEYS = {
12
+ consumed: [:consumed, :c].freeze,
13
+ point: [:point, :p].freeze,
14
+ nid: [:nid].freeze,
15
+ exid: [:exid].freeze,
16
+ domain: [:domain, :d].freeze,
17
+ subdomain: [:subdomain, :sd].freeze,
18
+ tag: [:tag, :t].freeze,
19
+ name: [:name, :n].freeze,
20
+ subnid: [:subnid].freeze,
21
+ heap: [:heap, :hp].freeze,
22
+ heat: [:heat, :ht].freeze
23
+ }.freeze
24
+
8
25
  def initialize(unit)
9
26
 
10
27
  @unit = unit
@@ -54,7 +71,11 @@ module Flor
54
71
  end
55
72
  end
56
73
 
57
- hook = Flor::Hook.instantiate(@unit, hook) if hook.is_a?(Class)
74
+ hook = Flor::Hook.instantiate(@unit, hook) \
75
+ if hook.is_a?(Class)
76
+
77
+ name ||= hook.name \
78
+ if hook.respond_to?(:name) && hook.method(:name).arity < 1
58
79
 
59
80
  @hooks << [ name, opts, hook, block ]
60
81
  end
@@ -81,13 +102,10 @@ module Flor
81
102
 
82
103
  protected
83
104
 
84
- def o(opts, *keys)
85
-
86
- array = false
87
- array = keys.pop if keys.last == []
105
+ def o(opts, key, array: false)
88
106
 
89
107
  r = nil
90
- keys.each { |k| break r = opts[k] if opts.has_key?(k) }
108
+ KEYS[key].each { |k| break r = opts[k] if opts.has_key?(k) }
91
109
 
92
110
  return nil if r == nil
93
111
  array ? Array(r) : r
@@ -103,7 +121,7 @@ module Flor
103
121
 
104
122
  opts = hook.opts if hook.respond_to?(:opts) && opts.empty?
105
123
 
106
- c = o(opts, :consumed, :c)
124
+ c = o(opts, :consumed)
107
125
  return false if c == true && ! message['consumed']
108
126
  return false if c == false && message['consumed']
109
127
 
@@ -112,7 +130,7 @@ module Flor
112
130
  return false if hook.within_itself?(executor, message)
113
131
  end
114
132
 
115
- ps = o(opts, :point, :p, [])
133
+ ps = o(opts, :point, array: true)
116
134
  return false if ps && ! ps.include?(message['point'])
117
135
 
118
136
  if nid = o(opts, :nid)
@@ -127,24 +145,24 @@ module Flor
127
145
 
128
146
  dm = Flor.domain(message['exid'])
129
147
 
130
- if dm && ds = o(opts, :domain, :d, [])
148
+ if dm && ds = o(opts, :domain, array: true)
131
149
  return false \
132
150
  unless ds.find { |d| d.is_a?(Regexp) ? (!! d.match(dm)) : (d == dm) }
133
151
  end
134
152
 
135
- if dm && sds = o(opts, :subdomain, :sd, [])
153
+ if dm && sds = o(opts, :subdomain, array: true)
136
154
  return false \
137
155
  unless sds.find do |sd|
138
156
  dm[0, sd.length] == sd
139
157
  end
140
158
  end
141
159
 
142
- if ts = o(opts, :tag, :t, [])
160
+ if ts = o(opts, :tag, array: true)
143
161
  return false unless %w[ entered left ].include?(message['point'])
144
162
  return false unless includes?(ts, message['tags'])
145
163
  end
146
164
 
147
- if ns = o(opts, :name, :n)
165
+ if ns = o(opts, :name)
148
166
  name = message['name']
149
167
  return false \
150
168
  unless ns.find { |n|
@@ -166,12 +184,12 @@ module Flor
166
184
  end
167
185
  end
168
186
 
169
- if hps = o(opts, :heap, :hp, [])
187
+ if hps = o(opts, :heap, array: true)
170
188
  return false unless node ||= executor.node(message['nid'])
171
189
  return false unless includes?(hps, node['heap'])
172
190
  end
173
191
 
174
- if hts = o(opts, :heat, :ht, [])
192
+ if hts = o(opts, :heat, array: true)
175
193
  return false unless node ||= executor.node(message['nid'])
176
194
  return false unless includes?(hts, node['heat0'])
177
195
  end
@@ -180,4 +198,3 @@ module Flor
180
198
  end
181
199
  end
182
200
  end
183
-