flor 1.2.1 → 1.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e89a3c4accc6ee1eca033031352f4c6d20c9b42ffbcb44aebe3cca04b59bc128
4
- data.tar.gz: 30914f85dfb1f76de1877cdb60e977eff73cb1ee31d9dfa7b893160799b4c162
3
+ metadata.gz: 298a6b2c9d3752b561ee8933ae00ed7a3f63682fb758dbe899097c6f7f56c00d
4
+ data.tar.gz: 3e2602737b9de7a452549d0f8ed34752618b1322a5508d178abe6559d549c045
5
5
  SHA512:
6
- metadata.gz: 91cbcbbebccc7209554f49645a43876bf7f2743a77eac4a64ab3daf7f5fbfb8f2e7d566f6ffc03c932222aa2daf82e5674fd52a653bddd8b390b27cbb4714e1c
7
- data.tar.gz: 174730b60ab5366c9cae335644ace73722ff52dc34477754020817c630dfabe1f6710846e437bbb936cb76fb4922f04d1dc2ffd2fde64f4c80924bd3dd7a629f
6
+ metadata.gz: 28ae10c78676391537dde7cd7e0082338650c6aeba60fbcffa2ca5a4cb2dd2f168d7ff61019472c5f6f3d2216cabfe6e9bccb7cdae4856b513e0663f4d4ec362
7
+ data.tar.gz: 6379738cddfc5b74d37a30fa23260924649866b49dc670f37a0540a47a5079062288851ce07306350e227d73d0fd873f2199c3ea01b3399bce61572b8cebe497
data/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
+ ## flor 1.4.0 released 2021-11-10
6
+
7
+ * Add :tree to Execution#to_h
8
+ * Scaffold bin/flotojson
9
+
10
+
11
+ ## flor 1.3.1 released 2021-04-19
12
+
13
+ * Fix flor_pointers var deletion mechanism (type = ' var ')
14
+
15
+
16
+ ## flor 1.3.0 released 2021-04-13
17
+
18
+ * Insert a row flor_pointers for 'failure'
19
+
20
+
21
+ ## flor 1.2.2 released 2021-03-29
22
+
23
+ * Include data in flor_pointers
24
+ * Ensure flor_pointers name is a string
25
+
26
+
5
27
  ## flor 1.2.1 released 2021-03-22
6
28
 
7
29
  * If conf sto_db_logger is false, do not attach a logger to the db connection
@@ -149,7 +149,7 @@ class Flor::Node
149
149
  tree = lookup_tree(Flor.parent_nid(nid))
150
150
  return tree[1][cid] if tree
151
151
 
152
- #tree = lookup_tree(Flor.parent_nid(nid, true))
152
+ #tree = lookup_tree(Flor.parent_nid(nid, remove_subnid=true))
153
153
  #return tree[1][cid] if tree
154
154
  #
155
155
  # might become necessary at some point
@@ -5,7 +5,7 @@ class Flor::Procedure < Flor::Node
5
5
  # "Returning vars" variables to pass back to pass upon reply.
6
6
  # In the 'receive' messages, it's a hash under the key 'rvars'.
7
7
  #
8
- RVARS = %w[ idx ]
8
+ RVARS = %w[ idx ].freeze
9
9
 
10
10
  # Attributes that when given alone are turned to "true" attributes.
11
11
  #
@@ -13,7 +13,7 @@ class Flor::Procedure < Flor::Node
13
13
  #
14
14
  # The transformation occurs in Flor::Pro::Att ("_att").
15
15
  #
16
- TRUE_ATTS = %w[ flank off disabled ]
16
+ TRUE_ATTS = %w[ flank off disabled ].freeze
17
17
 
18
18
  class << self
19
19
 
@@ -550,6 +550,8 @@ class Flor::Procedure < Flor::Node
550
550
  wrap_reply
551
551
  end
552
552
 
553
+ IF_UNLESS = %w[ _if _unless ].freeze
554
+
553
555
  # Grab on_error proc from incoming payload and stores it into parent node.
554
556
  #
555
557
  # Has no effect if there is no parent node.
@@ -562,7 +564,7 @@ class Flor::Procedure < Flor::Node
562
564
  @node; loop do
563
565
  pnode = parent_node(pnode)
564
566
  return unless pnode
565
- break unless %w[ _if _unless ].include?(pnode['heap'])
567
+ break unless IF_UNLESS.include?(pnode['heap'])
566
568
  end
567
569
 
568
570
  flavour = "on_#{key}"
@@ -598,6 +600,8 @@ class Flor::Procedure < Flor::Node
598
600
  wrap('point' => 'entered', 'nid' => nid, 'tags' => ret)
599
601
  end
600
602
 
603
+ WRAP_KEYS = %w[ error cancel timeout ].freeze
604
+
601
605
  def wrap(h={})
602
606
 
603
607
  m = {}
@@ -642,7 +646,7 @@ class Flor::Procedure < Flor::Node
642
646
  # was considering passing the whole vars back (as 'varz'), but
643
647
  # it got in the way... and it might be heavy
644
648
 
645
- %w[ error cancel timeout ]
649
+ WRAP_KEYS
646
650
  .each { |k|
647
651
  co = @node["child_on_#{k}"]
648
652
  next unless co
data/lib/flor/log.rb CHANGED
@@ -343,7 +343,7 @@ module Flor
343
343
  o.puts(tree_to_s(node.lookup_tree(nid), nid, out: o)) if node
344
344
 
345
345
  o.puts "#{_c.dg}node:#{_c.yl}"
346
- o.puts YAML.dump(n.merge('tree' => '(above)'))
346
+ o.puts n ? YAML.dump(n.merge('tree' => '(above)')) : 'nil'
347
347
 
348
348
  o.puts "#{_c.dg}nodes:#{_c.yl}"
349
349
  o.puts nods_to_s(executor, m, opts)
data/lib/flor/parser.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Flor
3
4
 
4
5
  def self.parse(input, fname=nil, opts={})
@@ -727,3 +728,4 @@ fail "don't know how to invert #{operation.inspect}" # FIXME
727
728
  sio.string
728
729
  end
729
730
  end
731
+
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ # flotojson.rb
4
+
5
+ require 'flor'
6
+
7
+ FLAGS_WITH_VALUE = []
8
+
9
+ flags = {}
10
+ files = []
11
+
12
+ if (ARGV & [ '-h', '--help']).any?
13
+ puts
14
+ puts "bin/flotojson [flags] filename"
15
+ puts
16
+ puts " turns a flor .flo process definition to its tree representation"
17
+ puts
18
+ puts " flags:"
19
+ puts " --pp pretty prints instead of dumping as JSON"
20
+ puts
21
+ exit 0
22
+ end
23
+
24
+ args = ARGV.dup
25
+
26
+ loop do
27
+
28
+ a = args.shift; break unless a
29
+
30
+ if a.size > 1 && a[0, 1] == '-'
31
+ flags[a] = FLAGS_WITH_VALUE.include?(a) ? a.shift : true
32
+ else
33
+ files << a
34
+ end
35
+ end
36
+
37
+ #STDERR.puts flags.inspect
38
+ #STDERR.puts files.inspect
39
+
40
+ # t =
41
+ # tree.is_a?(String) ?
42
+ # Flor.parse(tree, opts[:fname] || opts[:path], opts) :
43
+ # tree
44
+ #
45
+ # unless t
46
+ #
47
+ # #h = opts.merge(prune: false, rewrite: false, debug: 0)
48
+ # #Raabro.pp(Flor.parse(tree, h[:fname], h))
49
+ # # TODO re-parse and indicate what went wrong...
50
+ #
51
+ # fail ArgumentError.new(
52
+ # "flow parsing failed: " + tree.inspect[0, 35] + '...')
53
+ # end
54
+
55
+ fname = files.first
56
+ content = File.read(fname)
57
+ tree = Flor.parse(content, fname, {})
58
+
59
+ if flags['--pp']
60
+ pp tree
61
+ else
62
+ puts JSON.dump(tree)
63
+ end
64
+
@@ -20,7 +20,29 @@ module Flor
20
20
  #end
21
21
 
22
22
  def nodes; data['nodes']; end
23
+
23
24
  def zero_node; nodes['0']; end
25
+
26
+ # Returns the nids, the lower in the tree, the earlier in the returned
27
+ # array.
28
+ #
29
+ def sorted_nids
30
+
31
+ nodes.keys
32
+ .inject([]) { |a, nid|
33
+ l = nid.split('_').length
34
+ (a[l] ||= []) << nid
35
+ a }
36
+ .compact
37
+ .collect(&:sort)
38
+ .flatten(1)
39
+ end
40
+
41
+ def lowest_node
42
+
43
+ nodes[sorted_nids.first]
44
+ end
45
+
24
46
  def closing_messages; data['closing_messages']; end
25
47
 
26
48
  def execution(reload=false); self; end
@@ -47,14 +69,16 @@ module Flor
47
69
 
48
70
  def full_tree
49
71
 
50
- tree = nodes['0']['tree']
72
+ nids = sorted_nids
73
+ nid0 = nids.shift
51
74
 
52
- #nodes.each do |nid, n|
53
- # next if nid == '0'
54
- # t = n['tree']; next unless t
55
- #end
56
- #
57
- # FIXME
75
+ return nil unless nid0
76
+
77
+ tree = Flor.dup(nodes[nid0]['tree'])
78
+
79
+ nids.each { |nid|
80
+ next unless nid.split('_', 2).first == nid0
81
+ replace_sub_tree(tree, nid, nodes[nid]['tree']) }
58
82
 
59
83
  tree
60
84
  end
@@ -80,21 +104,22 @@ module Flor
80
104
  cs = m[:counts] = {}
81
105
  is = m[:nids] = { tasks: [], failures: [] }
82
106
 
83
- fs = 0
84
- ts = 0
107
+ cs[:failures] = 0
108
+ cs[:tasks] = 0
109
+ cs[:nodes] = nodes.count
110
+ #
85
111
  nodes.each do |k, v|
86
112
  if v['task']
87
- ts += 1
113
+ cs[:tasks] += 1
88
114
  is[:tasks] << k
89
115
  end
90
116
  if v['failure']
91
- fs += 1
117
+ cs[:failures] += 1
92
118
  is[:failures] << k
93
119
  end
94
120
  end
95
- cs[:nodes] = nodes.count
96
- cs[:failures] = fs
97
- cs[:tasks] = ts
121
+
122
+ h[:tree] = full_tree
98
123
 
99
124
  h
100
125
  end
@@ -149,6 +174,30 @@ module Flor
149
174
  lookup_node(query, opts)['nid']
150
175
  end
151
176
 
177
+ protected
178
+
179
+ def replace_sub_tree(tree, nid, t)
180
+
181
+ return unless t
182
+ return if nid.index('-') # stay vanilla
183
+
184
+ snid = nid.split('_').collect(&:to_i)[1..-1]
185
+ a = get_child_array(tree, snid)
186
+
187
+ return unless a # shouldn't we fail?
188
+
189
+ a[snid.first] = Flor.dup(t)
190
+ end
191
+
192
+ def get_child_array(tree, snid)
193
+
194
+ return nil if tree.nil?
195
+ return nil if snid.length < 1
196
+ return nil unless tree[1].is_a?(Array)
197
+ return tree[1] if snid.length == 1
198
+ n = snid.shift; get_child_array(tree[1][n], snid)
199
+ end
200
+
152
201
  class << self
153
202
 
154
203
  def by_status(s)
@@ -242,18 +242,18 @@ module Flor
242
242
  end
243
243
  end
244
244
 
245
+ RETURN_KEYS = %w[ exid nid payload tasker cause ].freeze
246
+
245
247
  def return(message)
246
248
 
247
- m =
249
+ queue(
248
250
  if message['point'] == 'failed'
249
251
  message
250
252
  else
251
253
  message
252
- .select { |k, _| %w[ exid nid payload tasker cause ].include?(k) }
254
+ .select { |k, _| RETURN_KEYS.include?(k) }
253
255
  .merge!('point' => 'return')
254
- end
255
-
256
- queue(m)
256
+ end)
257
257
 
258
258
  nil
259
259
  end
@@ -432,7 +432,7 @@ module Flor
432
432
  ex ? ex.execution : nil
433
433
  end
434
434
 
435
- DUMP_KEYS = %w[ timestamp executions timers traps pointers ]
435
+ DUMP_KEYS = %w[ timestamp executions timers traps pointers ].freeze
436
436
 
437
437
  # Dumps all or some of the executions to a JSON string.
438
438
  # See Scheduler#load for importing.
@@ -598,6 +598,8 @@ module Flor
598
598
  puts(on_start_exc(ex))
599
599
  end
600
600
 
601
+ PREP_KEYS = %w[ exid name nid payload on_receive_last ].freeze
602
+
601
603
  def prepare_message(point, args)
602
604
 
603
605
  h = args
@@ -612,7 +614,7 @@ module Flor
612
614
  opts = {}
613
615
 
614
616
  h.each do |k, v|
615
- if %w[ exid name nid payload on_receive_last ].include?(k)
617
+ if PREP_KEYS.include?(k)
616
618
  msg[k] = v
617
619
  else
618
620
  opts[k.to_sym] = v
@@ -12,8 +12,9 @@ module Flor
12
12
  :status, :ctime, :mtime, :cunit, :munit
13
13
  ].freeze
14
14
  POINTER_COLUMNS = [
15
- :domain, :exid, :nid, :type, :name, :value, :ctime, :cunit
16
- ].freeze
15
+ :domain, :exid, :nid, :type, :name, :value, :ctime, :cunit,
16
+ :content
17
+ ].freeze
17
18
 
18
19
  attr_reader :unit, :db, :models
19
20
 
@@ -219,6 +220,9 @@ module Flor
219
220
  raise err
220
221
  end
221
222
 
223
+ CRECON_STATUSES = %w[ created consumed ].freeze
224
+ RESCON_STATUSES = %w[ reserved consumed ].freeze
225
+
222
226
  def load_messages(exe_count)
223
227
 
224
228
  exe_count += 2
@@ -229,12 +233,12 @@ module Flor
229
233
  _exids_being_processed =
230
234
  @db[:flor_messages]
231
235
  .select(:exid)
232
- .exclude(status: %w[ created consumed ])
236
+ .exclude(status: CRECON_STATUSES)
233
237
  _exids =
234
238
  @db[:flor_messages]
235
239
  .select(:exid)
236
240
  .exclude(exid: _exids_being_processed)
237
- .exclude(status: %w[ reserved consumed ])
241
+ .exclude(status: RESCON_STATUSES)
238
242
  .limit(exe_count)
239
243
  @db[:flor_messages]
240
244
  .where(exid: _exids, status: 'created')
@@ -317,7 +321,7 @@ module Flor
317
321
  []
318
322
  end
319
323
 
320
- POINTS_TO_ARCHIVE = %w[ terminated failed ceased ]
324
+ POINTS_TO_ARCHIVE = %w[ terminated failed ceased ].freeze
321
325
 
322
326
  def consume(messages)
323
327
 
@@ -685,6 +689,8 @@ module Flor
685
689
  # done in update_pointers
686
690
  end
687
691
 
692
+ FP_TYPES = %w[ var ].freeze
693
+
688
694
  def update_pointers(exe, status, now)
689
695
 
690
696
  # Q Should we archive old pointers?
@@ -700,7 +706,7 @@ module Flor
700
706
 
701
707
  @db[:flor_pointers]
702
708
  .where(exid: exid)
703
- .where(Sequel.|({ type: %w[ var ] }, Sequel.~(nid: exe['nodes'].keys)))
709
+ .where(Sequel.|({ type: FP_TYPES }, Sequel.~(nid: exe['nodes'].keys)))
704
710
  .delete
705
711
  #
706
712
  # Delete all pointer to vars, their value might have changed,
@@ -713,28 +719,57 @@ module Flor
713
719
  pointers = exe['nodes']
714
720
  .inject([]) { |a, (nid, node)|
715
721
 
722
+ # add a pointer for each tag
723
+
716
724
  ts = node['tags']
717
725
  ts.each { |t|
718
726
  a << [ dom, exid, nid, 'tag', t, nil, now, u, nil ] } if ts
719
727
 
728
+ # add a pointer for each var (if nid == '0')
729
+
720
730
  vs = nid == '0' ? node['vars'] : nil
721
731
  vs.each { |k, v|
722
732
  case v; when Numeric, String, TrueClass, FalseClass, NilClass
723
- a << [ dom, exid, '0', 'var', k, v.to_s, now, u, nil ]
733
+ a << [ dom, exid, '0', 'var', k, v.to_s, now, u, v ]
724
734
  when Array, Hash
725
735
  s = '(array)'; s = '(object)' if v.is_a?(Hash)
726
- a << [ dom, exid, '0', 'var', k, s, now, u, nil ]
736
+ a << [ dom, exid, '0', 'var', k, s, now, u, v ]
727
737
  else
728
- a << [ dom, exid, '0', 'var', k, nil, now, u, nil ]
738
+ a << [ dom, exid, '0', 'var', k, nil, now, u, v ]
729
739
  end } if vs
730
740
 
741
+ # add a pointer for the task if any
742
+
731
743
  if ta = node['task']
732
744
  tasker = ta['tasker']
733
- name = ta['name']
745
+ n = ta['name']; name = n.is_a?(String) ? n : JSON.dump(n)
734
746
  content = { message: node['message'], atts: node['atts'] }
735
747
  a << [ dom, exid, nid, 'tasker', tasker, name, now, u, content ]
736
748
  end
737
749
 
750
+ # add a pointer for the error if any
751
+
752
+ if fa = node['failure']
753
+
754
+ #puts "-" * 80; pp node; puts "-" * 80
755
+ a <<
756
+ if er = fa['error']
757
+ ni = fa['from'] || nid # not nid /!\
758
+ nam = "#{er['kla']} l#{er['lin']}"
759
+ val = er['msg']
760
+ con = { error: fa, nid: ni }
761
+ [ dom, exid, ni, 'failure', nam, val, now, u, con ]
762
+ else
763
+ nam = fa['tasker'] || 'failure'
764
+ val = [ fa['attl'] || [], fa['attd'] || {} ]
765
+ .collect(&:inspect).join(' ')
766
+ con = { error: fa, nid: nid }
767
+ [ dom, exid, nid, 'failure', nam, val, now, u, con ]
768
+ end
769
+ end
770
+
771
+ # done
772
+
738
773
  a }
739
774
 
740
775
  cps = @db[:flor_pointers] # current pointers
@@ -746,29 +781,22 @@ module Flor
746
781
  #
747
782
  # don't insert when already inserted
748
783
 
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
784
+ pointers.each { |ptr| c = ptr[8]; ptr[8] = to_blob(c) if c }
756
785
 
757
786
  @db[:flor_pointers]
758
787
  .import(
759
- pointer_columns,
788
+ POINTER_COLUMNS,
760
789
  pointers)
761
790
  end
762
791
 
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
792
+ #def pointer_columns
793
+ # @pointer_columns ||=
794
+ # if @db[:flor_pointers].columns.include?(:content)
795
+ # POINTER_COLUMNS + [ :content ]
796
+ # else
797
+ # POINTER_COLUMNS
798
+ # end
799
+ #end
772
800
 
773
801
  def determine_type_and_schedule(message)
774
802
 
data/lib/flor.rb CHANGED
@@ -16,7 +16,7 @@ require 'dense'
16
16
 
17
17
  module Flor
18
18
 
19
- VERSION = '1.2.1'
19
+ VERSION = '1.4.0'
20
20
  end
21
21
 
22
22
  require 'flor/colours'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-22 00:00:00.000000000 Z
11
+ date: 2021-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: munemo
@@ -249,6 +249,7 @@ files:
249
249
  - lib/flor/to_string.rb
250
250
  - lib/flor/tools/env.rb
251
251
  - lib/flor/tools/firb.rb
252
+ - lib/flor/tools/flotojson.rb
252
253
  - lib/flor/tools/shell.rb
253
254
  - lib/flor/tools/shell_out.rb
254
255
  - lib/flor/tt.rb