flor 0.18.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +3 -0
  3. data/CREDITS.md +1 -0
  4. data/LICENSE.txt +1 -1
  5. data/Makefile +1 -1
  6. data/README.md +15 -1
  7. data/flor.gemspec +1 -2
  8. data/lib/flor.rb +2 -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 +20 -16
  13. data/lib/flor/core/node.rb +1 -13
  14. data/lib/flor/core/procedure.rb +10 -1
  15. data/lib/flor/core/texecutor.rb +9 -2
  16. data/lib/flor/djan.rb +1 -0
  17. data/lib/flor/errors.rb +1 -0
  18. data/lib/flor/flor.rb +144 -15
  19. data/lib/flor/id.rb +1 -0
  20. data/lib/flor/log.rb +2 -1
  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 +1 -0
  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 +1 -0
  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 +4 -3
  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 +1 -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 +1 -0
  117. data/lib/flor/punit/c_map.rb +1 -0
  118. data/lib/flor/punit/cancel.rb +1 -0
  119. data/lib/flor/punit/concurrence.rb +1 -0
  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 +1 -0
  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 +1 -0
  129. data/lib/flor/punit/sleep.rb +1 -0
  130. data/lib/flor/punit/task.rb +1 -0
  131. data/lib/flor/punit/trace.rb +1 -0
  132. data/lib/flor/punit/trap.rb +10 -1
  133. data/lib/flor/to_string.rb +1 -0
  134. data/lib/flor/tools/env.rb +1 -0
  135. data/lib/flor/tools/shell.rb +1 -0
  136. data/lib/flor/tools/shell_out.rb +1 -0
  137. data/lib/flor/tt.rb +98 -0
  138. data/lib/flor/unit.rb +2 -0
  139. data/lib/flor/unit/caller.rb +152 -19
  140. data/lib/flor/unit/caller_jruby.rb +132 -0
  141. data/lib/flor/unit/dump.rb +36 -0
  142. data/lib/flor/unit/executor.rb +1 -0
  143. data/lib/flor/unit/ganger.rb +6 -12
  144. data/lib/flor/unit/hloader.rb +34 -7
  145. data/lib/flor/unit/hook.rb +3 -0
  146. data/lib/flor/unit/hooker.rb +32 -15
  147. data/lib/flor/unit/journal.rb +23 -0
  148. data/lib/flor/unit/loader.rb +102 -7
  149. data/lib/flor/unit/logger.rb +24 -5
  150. data/lib/flor/unit/models.rb +8 -1
  151. data/lib/flor/unit/models/execution.rb +51 -0
  152. data/lib/flor/unit/models/message.rb +1 -0
  153. data/lib/flor/unit/models/pointer.rb +1 -0
  154. data/lib/flor/unit/models/timer.rb +1 -0
  155. data/lib/flor/unit/models/trace.rb +1 -0
  156. data/lib/flor/unit/models/trap.rb +3 -2
  157. data/lib/flor/unit/scheduler.rb +35 -28
  158. data/lib/flor/unit/spooler.rb +1 -0
  159. data/lib/flor/unit/storage.rb +68 -44
  160. data/lib/flor/unit/taskers.rb +2 -1
  161. data/lib/flor/unit/waiter.rb +2 -1
  162. data/lib/flor/unit/wlist.rb +10 -8
  163. metadata +13 -10
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flor
4
+
5
+ class Caller
6
+
7
+ def split_cmd(cmd)
8
+
9
+ #cmd.split(/ +/)
10
+ # too naive
11
+
12
+ #Raabro.pp(Flor::Caller::CmdParser.parse(cmd, debug: 3), colours: true)
13
+ Flor::Caller::CmdParser.parse(cmd)
14
+ end
15
+
16
+ class ProcessStatus
17
+
18
+ attr_reader :process, :exitstatus
19
+
20
+ def initialize(process, exitstatus)
21
+
22
+ @process = process
23
+ @exitstatus = exitstatus
24
+ end
25
+
26
+ def pid; @process.pid; end
27
+ end
28
+
29
+ def spawn(conf, data)
30
+
31
+ t0 = Time.now
32
+
33
+ cmd = conf['cmd']
34
+ henv, *acmd = split_cmd(cmd)
35
+
36
+ to = Fugit.parse(conf['timeout'] || '14s')
37
+ to = to.is_a?(Fugit::Duration) ? to.to_sec : 14
38
+ to = 0 if to < 0 # no timeout
39
+
40
+ builder = java.lang.ProcessBuilder.new(*acmd)
41
+ henv.each { |k, v| builder.environment.put(k, v) }
42
+
43
+ process = builder.start
44
+ pid = process.pid
45
+
46
+ o = process.outputStream.to_io
47
+ i = process.inputStream.to_io
48
+ f = process.errorStream.to_io
49
+
50
+ o.write(data)
51
+ o.close
52
+
53
+ ex = timeout(to) { process.waitFor }
54
+
55
+ status = ProcessStatus.new(process, ex)
56
+
57
+ fail SpawnNonZeroExitError.new(conf, { to: to, t0: t0 }, status, i, f) \
58
+ if status.exitstatus != 0
59
+
60
+ [ i.read, status ]
61
+
62
+ rescue => err
63
+
64
+ Process.detach(pid) \
65
+ if pid
66
+ (Process.kill(9, pid) rescue nil) \
67
+ unless Flor.no?(conf['on_error_kill'])
68
+
69
+ raise err if err.is_a?(SpawnError)
70
+ raise WrappedSpawnError.new(conf, { to: to, t0: t0, pid: pid }, err)
71
+
72
+ ensure
73
+
74
+ [ i, o, f ].each { |x| x.close rescue nil }
75
+
76
+ end
77
+
78
+ module CmdParser include Raabro
79
+
80
+ # parsing
81
+
82
+ def separator(i); rex(nil, i, /[ ]+/); end
83
+
84
+ def dqstring(i); rex(:string, i, /"(\\"|[^"])*"/); end
85
+ def sqstring(i); rex(:string, i, /'(\\'|[^'])*'/); end
86
+
87
+ def word(i); rex(:word, i, /[^ "']+/); end
88
+ def item(i); alt(nil, i, :word, :sqstring, :dqstring); end
89
+ def cmd(i); jseq(:cmd, i, :item, :separator); end
90
+
91
+ def equal(i); rex(nil, i, /[ ]*=[ ]*/); end
92
+ def vval(i); alt(:vval, i, :word, :sqstring, :dqstring); end
93
+ def vkey(i); rex(:vkey, i, /[a-zA-Z_][a-zA-Z_0-9]*/); end
94
+ def var(i); seq(:var, i, :vkey, :equal, :vval, :separator); end
95
+
96
+ def cmdline(i); seq(:cmdline, i, :var, '*', :cmd) end
97
+
98
+ # rewriting
99
+
100
+ def rewrite_word(t); t.string; end
101
+
102
+ def rewrite_string(t)
103
+ s = t.string[1..-2]
104
+ s == 'sleep' ? t.string : s # ah, the awful thing :-(
105
+ end
106
+ #
107
+ # because of `ruby -e "sleep"` :-( is there another way?
108
+
109
+ def rewrite_cmd(t)
110
+
111
+ t.subgather(nil).collect { |tt| rewrite(tt) }
112
+ end
113
+
114
+ def rewrite_vars(ts)
115
+
116
+ ts.inject({}) { |h, t|
117
+ k = t.lookup(:vkey).string
118
+ v = t.lookup(:vval).string; v = v[1..-2] unless t.lookup(:word)
119
+ h[k] = v
120
+ h }
121
+ end
122
+
123
+ def rewrite_cmdline(t)
124
+
125
+ #Raabro.pp(t, colours: true)
126
+ [ rewrite_vars(t.subgather(:var)),
127
+ *t.lookup(:cmd).subgather(nil).collect { |tt| rewrite(tt) } ]
128
+ end
129
+ end
130
+ end
131
+ end
132
+
@@ -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
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -66,11 +67,15 @@ module Flor
66
67
  tconf = tconf.find { |h| points.include?(h['point']) }
67
68
  end
68
69
 
70
+ fail ArgumentError.new(
71
+ "tconf #{tconf.inspect} not a hash"
72
+ ) unless tconf.is_a?(Hash)
73
+
69
74
  message['tconf'] = tconf unless tconf['include_tconf'] == false
70
75
 
71
76
  message['vars'] = gather_vars(executor, tconf, message)
72
77
 
73
- m = dup_message(message)
78
+ m = Flor.dup_message(message)
74
79
  #
75
80
  # the tasker gets a copy of the message (and it can play with it
76
81
  # to its heart content), meanwhile the message is handed to the
@@ -92,17 +97,6 @@ module Flor
92
97
 
93
98
  protected
94
99
 
95
- def dup_message(m)
96
-
97
- tc = m.delete('tconf')
98
- m1 = Flor.dup(m)
99
- m1['tconf'] = tc.inject({}) { |h, (k, v)|
100
- h[k] = k == 'class' ? v : Flor.dup(v); h } \
101
- if tc
102
-
103
- m1
104
- end
105
-
106
100
  def var_match(k, filter)
107
101
 
108
102
  filter.each { |f| return true if (f.is_a?(String) ? k == f : f.match(k)) }
@@ -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
-
@@ -1,13 +1,24 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
5
+ # A Journal hook, receives only "consumed" messages and
6
+ # keeps a copy of all of them.
7
+ #
8
+ # Used in specs, do not uses as-is in production, since it simply
9
+ # grows in memory...
10
+ #
4
11
  class Journal
5
12
 
6
13
  attr_reader :messages
7
14
 
8
15
  def initialize(unit)
9
16
 
17
+ # Add a #journal method to the flor unit so that
18
+ # `unit.journal` yields the message list.
19
+ #
10
20
  unit.singleton_class.instance_eval do
21
+
11
22
  define_method(:journal) do
12
23
  @hooker['journal'].messages
13
24
  end
@@ -16,11 +27,23 @@ module Flor
16
27
  @messages = []
17
28
  end
18
29
 
30
+ # Tells the hooker that this hook is only interested in message that
31
+ # have been "consumed", remember, the hooker passes messages to
32
+ # hooks before consumption and after consumption. In this case only
33
+ # consumed messages are passed.
34
+ #
35
+ # Other hooks may declare they are only interested in messages
36
+ # belonging to a certain domain or having a certain tag.
37
+ # See spec/unit/unit_hooks_spec.rb for more filtering examples.
38
+ #
19
39
  def opts; { consumed: true }; end
20
40
 
41
+ # The method used by the hooker to give consumed messages to this journal
42
+ #
21
43
  def notify(executor, message)
22
44
 
23
45
  @messages << Flor.dup(message)
46
+ # stores a deep clone of each consumed message
24
47
 
25
48
  [] # no new messages
26
49
  end