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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b74ff25bb24e46910557e440ddedc83d07730ec5
4
- data.tar.gz: cc0d4de7df8c9a3e39879dfd8968ae70230310c7
2
+ SHA256:
3
+ metadata.gz: 7a1f76874a9957b7c15c59baf997e0e60ff4872b9109a7cd741692735a94565c
4
+ data.tar.gz: 7fd1552910609023dd8bce0de0d5b5fc1ebc5ae1674fc27f0d0cb932c4bab2a7
5
5
  SHA512:
6
- metadata.gz: b2085152306c18636cbd64e9e5d3bc140e6d3b19f2d8afc4111d5283e9da56328a7fc09ab5c2db5fa14f429f3f5f858b87c67c3c6defcb790cb34042608871cb
7
- data.tar.gz: 52c344d0deb517f025eb7491201175d44356257c7fae1cad36e8f0a7006a60ec10a3829e0bbc1e7cae2781a0a2ad434e6e84f7499ef9cac94cb0ca095df91643
6
+ metadata.gz: cbca621e72efc0bdf1df26a4554590032f7a42d76ca19b361305f519071f1f026678c55c2980e74661ebcd5ac018d9e3e892376ee69a07c91ebb1d2d809cbb75
7
+ data.tar.gz: b2c7cbe0a13c12f0e9b935c3d675f583d93a4f78f921982e75eb9050c84d97914c63cf9280667b5be977280cda9de27a57972f3f0d72b097710a6b3b1e45d67b
@@ -2,6 +2,9 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
+ ## flor 0.19.0 not yet released
6
+
7
+
5
8
  ## flor 0.18.0 released 2019-05-05
6
9
 
7
10
  * Refine BasicTasker#reply (more arg patterns)
data/CREDITS.md CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  ## Contributors
5
5
 
6
+ * Olle Jonsson - https://github.com/olleolleolle
6
7
  * Ryan Scott - https://github.com/Subtletree
7
8
  * Jeffrey Hicks - https://github.com/jrhicks
8
9
  * David Verrier - https://github.com/dverrier
@@ -1,5 +1,5 @@
1
1
 
2
- Copyright (c) 2015-2019, John Mettraux, jmettraux+flor@gmail.com
2
+ Copyright (c) 2015-2020, John Mettraux, jmettraux+flor@gmail.com
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to deal
data/Makefile CHANGED
@@ -32,7 +32,7 @@ build: gemspec_validate
32
32
  mv $(NAME)-$(VERSION).gem pkg/
33
33
 
34
34
  push: build
35
- gem push pkg/$(NAME)-$(VERSION).gem
35
+ gem push --otp "$(OTP)" pkg/$(NAME)-$(VERSION).gem
36
36
 
37
37
 
38
38
  ## flor tasks ##
data/README.md CHANGED
@@ -11,6 +11,17 @@ Flor is a "Ruby workflow engine", if that makes any sense.
11
11
  * [twitter.com/@flor_workflow](https://twitter.com/flor_workflow)
12
12
 
13
13
 
14
+ ## use
15
+
16
+ As a workflow engine, flor takes as input process definitions and executes them. Those executions may in turn call pieces of Ruby code or external scripts that perform the actual work. Those pieces of code and scripts are called "taskers".
17
+
18
+ The classical way to use a language interpreter is to instantiate it as needed and let it die as the host execution ends. A workflow engine is more like a server, it may host multiple executions. And if the workflow engine stops, it may be restarted and pick the work back, when it was when it stopped.
19
+
20
+ Flor process definitions are written in the flor language, a programming language mostly inspired by Scheme and Ruby. As always with programming languages, readability is hoped for, for a workflow engine this is especially necessary since those business processes are the bread and butter of business users.
21
+
22
+ Using flor in your Ruby project requires you to clearly separate business process definitions from taskers. Since a flor instance may host multiple process executions based on one or more process definitions, many of the taskers may be reused from one definition to the other. For instance, if a "send-invoice-to-customer" tasker is created it might get used in the "process-retail-order" and the "process-big-distribution-order" processes.
23
+
24
+
14
25
  ## design
15
26
 
16
27
  * Strives to propose a scheming interpreter for long running executions
@@ -123,8 +134,11 @@ There are various other Ruby and Ruby on Rails projects about workflows and busi
123
134
 
124
135
  * [Dynflow](http://dynflow.github.io/) - "Dynflow (DYNamic workFLOW) is a workflow engine written in Ruby"
125
136
  * [rails_workflow](https://github.com/madzhuga/rails_workflow) - "Rails Workflow Engine allows you to organize your application business logic by joining user- and auto- operations in processes"
126
- * [rails_engine/workflow_core](https://github.com/rails-engine/workflow_core) - "A Rails engine which providing essential infrastructure of workflow. It's based on Workflow Nets"
137
+ * [rails_engine/flow_core](https://github.com/rails-engine/flow_core) - "A multi purpose, extendable, Workflow-net-based workflow engine for Rails applications"
127
138
  * [Trailblazer](http://trailblazer.to/) - "The Advanced Business Logic Framework"
139
+ * [Petri Flow](https://github.com/hooopo/petri_flow) - "Petri Net Workflow Engine for Ruby" (Rails)
140
+ * [Pallets](https://github.com/linkyndy/pallets) - "Simple and reliable workflow engine, written in Ruby"
141
+ * [Gush](https://github.com/chaps-io/gush) - "Fast and distributed workflow runner using ActiveJob and Redis"
128
142
 
129
143
  There is a [workflow engine](https://ruby.libhunt.com/categories/5786-workflow-engine) category on [Awesome Ruby](https://ruby.libhunt.com/).
130
144
 
@@ -10,8 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.authors = [ 'John Mettraux' ]
12
12
  s.email = [ 'jmettraux+flor@gmail.com' ]
13
- s.homepage = 'http://github.com/floraison'
14
- #s.rubyforge_project = 'flor'
13
+ s.homepage = 'https://github.com/floraison'
15
14
  s.license = 'MIT'
16
15
  s.summary = 'A Ruby workflow engine'
17
16
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require 'pp'
3
4
  require 'json'
@@ -14,8 +15,7 @@ require 'dense'
14
15
 
15
16
  module Flor
16
17
 
17
- VERSION = '0.18.0'
18
- #VERSION = '1.0.0'
18
+ VERSION = '1.0.0'
19
19
  end
20
20
 
21
21
  require 'flor/colours'
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
4
5
  COLS = Hash[*%w[
5
6
 
6
7
  reset 0;0
7
- bright 1 dim 2 underlined 4 blink 5 reverse 7 hidden 8 default 39
8
+ bright 1 dim 2 underlined 4 blink 5 reverse 7 hidden 8 strike 9 default 39
8
9
  black 30 red 31 green 32 yellow 33 blue 34 magenta 35 cyan 36
9
10
  light_gray 37 dark_gray 90 light_red 91 light_green 92
10
11
  light_yellow 93 light_blue 94 light_magenta 95 light_cyan 96 white 97
@@ -17,7 +18,8 @@ module Flor
17
18
  brown yellow purple magenta dark_grey dark_gray light_grey light_gray
18
19
 
19
20
  rd red bl blue bu blue ba black bk black gn green gr green dg dark_gray
20
- gy light_gray lg light_gray yl yellow y yellow ma magenta rs reset
21
+ gy light_gray lg light_gray yl yellow y yellow ma magenta wt white
22
+ rs reset
21
23
  br bright bri bright un underlined rv reverse bn blink blg bg_light_gray
22
24
  und underlined rev reverse
23
25
  ]]
@@ -28,7 +30,7 @@ module Flor
28
30
  if v.match(/\A\d/)
29
31
  class_eval(%{
30
32
  def #{k}(s=nil)
31
- s ? "[#{v}m" + s + "" : "[#{v}m"
33
+ s ? "[#{v}m" + s + "" : "[#{v}m"
32
34
  end })
33
35
  else
34
36
  class_eval(
@@ -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
 
@@ -28,7 +29,7 @@ module Flor
28
29
 
29
30
  t =
30
31
  tree.is_a?(String) ?
31
- Flor.parse(tree, opts[:fname], opts) :
32
+ Flor.parse(tree, opts[:fname] || opts[:path], opts) :
32
33
  tree
33
34
 
34
35
  unless t
@@ -51,13 +52,13 @@ module Flor
51
52
  "given launch variables should come in a Hash, but it's a #{vs.class}"
52
53
  ) unless vs.is_a?(Hash)
53
54
 
54
- msg =
55
- { 'point' => 'execute',
56
- 'exid' => exid,
57
- 'nid' => '0',
58
- 'tree' => t,
59
- 'payload' => pl,
60
- 'vars' => vs }
55
+ msg = {
56
+ 'point' => 'execute',
57
+ 'exid' => exid,
58
+ 'nid' => '0',
59
+ 'tree' => t,
60
+ 'payload' => pl,
61
+ 'vars' => vs }
61
62
 
62
63
  msg['vdomain'] = opts[:vdomain] \
63
64
  if opts.has_key?(:vdomain)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -211,7 +212,8 @@ module Flor
211
212
  #
212
213
  # tag: et al
213
214
 
214
- node['tree'] = message['tree'] = t = [ '_sqs', tree[0], tree[2] ]
215
+ node['tree'] = message['tree'] = t =
216
+ [ '_sqs', tree[0], tree[2] ]
215
217
 
216
218
  node['heat0'] = t[0]
217
219
  node['heat'] = h = n.deref(t[0])
@@ -221,14 +223,16 @@ module Flor
221
223
  #
222
224
  # rewrite `alpha` into `task alpha`
223
225
 
224
- l = message['tree'][2]
226
+ mt = message['tree']
227
+ l = mt[2]
225
228
 
226
- message['otree'] = Flor.dup(message['tree'])
229
+ message['otree'] = mt
227
230
 
228
- message['tree'][0] =
229
- 'task'
230
- message['tree'][1].unshift(
231
- [ '_att', [ [ '_sqs', heat[1]['tasker'], l ] ], l ])
231
+ node['tree'] = message['tree'] =
232
+ [ 'task', [
233
+ [ '_att', [ [ '_sqs', heat[1]['tasker'], l ] ], l ],
234
+ *mt[1]
235
+ ], l ]
232
236
  end
233
237
  end
234
238
 
@@ -287,9 +291,8 @@ end
287
291
 
288
292
  def receive(message)
289
293
 
290
- messages = leave_node(message)
291
-
292
294
  nid = message['nid']
295
+ messages = leave_node(message)
293
296
 
294
297
  return messages + toc_messages(message) unless nid
295
298
  # 'terminated' or 'ceased'
@@ -319,7 +322,9 @@ end
319
322
  cls = node['closures']
320
323
 
321
324
  pro = Flor::Procedure.make(self, node, message)
325
+
322
326
  pro.end
327
+ # do end the node
323
328
 
324
329
  cancels = pro.send(:wrap_cancel_children, 'cancel_trailing' => true)
325
330
 
@@ -380,12 +385,7 @@ end
380
385
 
381
386
  def error_reply(node, message, err)
382
387
 
383
- m = message
384
- .select { |k, v| %w[ sm exid nid from payload tree ].include?(k) }
385
-
386
- m['point'] = 'failed'
387
- m['fpoint'] = message['point']
388
- m['error'] = Flor.to_error(err)
388
+ m = Flor.to_error_message(message, err)
389
389
 
390
390
  @unit.logger.log_err(self, m, flag: true)
391
391
 
@@ -447,7 +447,11 @@ end
447
447
  stack_cause(message) \
448
448
  if %w[ trigger cancel ].include?(message['point'])
449
449
 
450
- determine_heat(message)
450
+ begin
451
+ determine_heat(message)
452
+ rescue => e
453
+ raise e unless message['point'] == 'failed'
454
+ end
451
455
 
452
456
  ms = []
453
457
  ms += @unit.notify(self, message) # pre
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  class Flor::Node
3
4
 
@@ -156,19 +157,6 @@ class Flor::Node
156
157
  nil
157
158
  end
158
159
 
159
- #def lookup_tree(nid)
160
- # climb_down_for_tree(nid) ||
161
- # climb_up_for_tree(nid) ||
162
- #end
163
- #def climb_up_for_tree(nid)
164
- # # ...
165
- #end
166
- #def climb_down_for_tree(nid)
167
- # # ...
168
- #end
169
- #
170
- # that might be the way...
171
-
172
160
  def lookup_value(path)
173
161
 
174
162
  original_path = path
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  class Flor::Procedure < Flor::Node
3
4
 
@@ -830,8 +831,16 @@ class Flor::Procedure < Flor::Node
830
831
  def wrap_cancel_nodes(nids, h)
831
832
 
832
833
  (nids || [])
833
- .collect { |i| wrap_cancel(h.merge('nid' => i, 'from' => nid)) }
834
+ .collect { |i|
835
+ n = @execution['nodes'][i]
836
+ s = n && n['status'].last
837
+ if n == nil || (s['status'] == 'closed' && s['point'] == 'cancel')
838
+ nil
839
+ else
840
+ wrap_cancel(h.merge('nid' => i, 'from' => nid))
841
+ end }
834
842
  .flatten(1)
843
+ .compact
835
844
  end
836
845
 
837
846
  def wrap_cancelled
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -235,7 +236,7 @@ module Flor
235
236
 
236
237
  c = ! (ENV['FLOR_DEBUG'] || '').match(/conf/)
237
238
  e = self.new('conf' => c)
238
- r = e.launch(source, payload: fs, vars: vs)
239
+ r = e.launch(source, payload: fs, vars: vs, path: path)
239
240
 
240
241
  unless r['point'] == 'terminated'
241
242
  ae = ArgumentError.new(
@@ -250,7 +251,7 @@ module Flor
250
251
  o['_path'] = path
251
252
  o['root'] ||= Flor.relativize_path(vs['root'])
252
253
  elsif o.is_a?(Array)
253
- o.each { |ee| ee['_path'] = path }
254
+ o.each { |ee| ee['_path'] = path if ee.is_a?(Hash) }
254
255
  end
255
256
 
256
257
  o
@@ -258,6 +259,12 @@ module Flor
258
259
 
259
260
  def interpret_path(path, context=nil)
260
261
 
262
+ path = File.join(path, 'etc/conf.json') if File.directory?(path)
263
+
264
+ fail ArgumentError.new(
265
+ "flor configuration file not found #{path.inspect}"
266
+ ) unless File.exist?(path)
267
+
261
268
  interpret(path, load(path), context || {})
262
269
  end
263
270
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require 'io/console'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  class Flor::FlorError < StandardError
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -77,6 +78,23 @@ module Flor
77
78
  deep_merge(o0, o1, true)
78
79
  end
79
80
 
81
+ def dup_message(m)
82
+
83
+ tc = m.delete('tconf')
84
+ m1 = Flor.dup(m)
85
+ m1['tconf'] = tc
86
+ .inject({}) { |h, (k, v)|
87
+ h[k] =
88
+ case k
89
+ when 'class' then v
90
+ else Flor.dup(v)
91
+ end
92
+ h
93
+ } if tc
94
+
95
+ m1
96
+ end
97
+
80
98
  def false?(o)
81
99
 
82
100
  o == nil || o == false
@@ -87,6 +105,20 @@ module Flor
87
105
  o != nil && o != false
88
106
  end
89
107
 
108
+ def yes?(o)
109
+
110
+ oo = o.respond_to?(:downcase) ? o.downcase : o
111
+
112
+ [ 'y', 'yes', 'true', true ].include?(o)
113
+ end
114
+
115
+ def no?(o)
116
+
117
+ oo = o.respond_to?(:downcase) ? o.downcase : o
118
+
119
+ [ 'n', 'no', 'false', false ].include?(o)
120
+ end
121
+
90
122
  def to_error(o)
91
123
 
92
124
  h = {}
@@ -109,19 +141,24 @@ module Flor
109
141
  h['cwd'] = Dir.pwd
110
142
  h['rlp'] = $: if o.is_a?(::LoadError)
111
143
 
144
+ h['details'] = o.details if o.respond_to?(:details)
145
+ h['details'] = o.flor_details if o.respond_to?(:flor_details)
146
+
112
147
  h
113
148
  end
114
149
 
115
- def to_error_message(message, err)
150
+ TO_ERROR_MESSAGE_KEYS = %w[ sm exid nid from payload tree er tasker ]
116
151
 
117
- m = message
118
- .select { |k, v|
119
- %w[ sm exid nid from payload tree er tasker ].include?(k) }
152
+ def to_error_message(message, error)
153
+
154
+ #puts "---"
155
+ #puts caller
156
+ m = message.select { |k, v| TO_ERROR_MESSAGE_KEYS.include?(k) }
120
157
 
121
158
  m['point'] = 'failed'
122
159
  m['fpoint'] = message['point']
123
160
  m['fm'] = message['m']
124
- m['error'] = to_error(err)
161
+ m['error'] = to_error(error)
125
162
 
126
163
  m
127
164
  end
@@ -337,6 +374,7 @@ module Flor
337
374
  sub == dom ||
338
375
  sub[0, dom.length + 1] == dom + '.'
339
376
  end
377
+ alias subdomain? sub_domain?
340
378
 
341
379
  def split_domain_unit(s)
342
380
 
@@ -385,6 +423,31 @@ module Flor
385
423
  (s ? (t[1] == s) : t[1].is_a?(String))
386
424
  end
387
425
 
426
+ def is_leaf_tree?(t)
427
+
428
+ t.is_a?(Array) &&
429
+ t[2].is_a?(Integer) &&
430
+ Flor::Pro::Atom.names.include?(t[0])
431
+ end
432
+ #alias is_atom_tree? is_leaf_tree?
433
+
434
+ # # Array, object or atom tree
435
+ # #
436
+ # def is_value_tree?(o)
437
+ #
438
+ # o.is_a?(Array) &&
439
+ # %w[ _num _boo _sqs _dqs _rxs _nul _arr _obj ].include?(o[0]) &&
440
+ # o[2].is_a?(Integer)
441
+ # end
442
+
443
+ def is_collection_tree?(t)
444
+
445
+ t.is_a?(Array) &&
446
+ (t[0] == '_arr' || t[0] == '_obj') &&
447
+ t[1].is_a?(Array)
448
+ end
449
+ alias is_coll_tree? is_collection_tree?
450
+
388
451
  def is_att_tree?(t)
389
452
 
390
453
  t.is_a?(Array) &&
@@ -418,15 +481,6 @@ module Flor
418
481
  t.is_a?(Array) && t[0].is_a?(String) && t[0] != '_' && t[1] == []
419
482
  end
420
483
 
421
- # # Array, object or atom tree
422
- # #
423
- # def is_value_tree?(o)
424
- #
425
- # o.is_a?(Array) &&
426
- # %w[ _num _boo _sqs _dqs _rxs _nul _arr _obj ].include?(o[0]) &&
427
- # o[2].is_a?(Integer)
428
- # end
429
-
430
484
  def is_proc_tree?(o)
431
485
 
432
486
  o.is_a?(Array) &&
@@ -483,7 +537,7 @@ module Flor
483
537
  def is_ref_tree?(o)
484
538
 
485
539
  o.is_a?(Array) &&
486
- (o[0] == '_ref' || o[0] == '_reff') &&
540
+ Flor::Pro::Ref.names.include?(o[0]) &&
487
541
  o[2].is_a?(Integer) &&
488
542
  o[1].is_a?(Array) &&
489
543
  o[1].all? { |e| is_sqs_tree?(e) || is_num_tree?(e) }
@@ -520,6 +574,81 @@ module Flor
520
574
  end
521
575
 
522
576
 
577
+ #
578
+ # tree to flor code
579
+
580
+ # Given a tree returns the equivalent flor piece of code
581
+ #
582
+ def tree_to_flor(t, opts={})
583
+
584
+ o = opts[:o] ||= StringIO.new
585
+ opts[:ind] ||= ''
586
+
587
+ t_to_flor(t, opts)
588
+
589
+ o.string
590
+ end
591
+
592
+ protected
593
+
594
+ def t_to_flor(t, opts)
595
+
596
+ o = opts[:o]
597
+ i = opts[:ind]
598
+
599
+ t1 = t[1]
600
+
601
+ return o << '_' if t[0, 2] == [ '_', [] ]
602
+ return c_to_flor(t, opts) if is_coll_tree?(t)
603
+ return o << JSON.dump(t1) if is_leaf_tree?(t)
604
+ return o << t1.collect { |a| a[1].to_s }.join('.') if is_ref_tree?(t)
605
+
606
+ o << i << t[0]
607
+
608
+ if t1.is_a?(Array)
609
+
610
+ atts, ctrees = t1.partition { |ct| is_att_tree?(ct) }
611
+
612
+ atts.each do |at|
613
+ ats = at[1]
614
+ o << ' '
615
+ if ats.length == 1
616
+ tree_to_flor(ats[0], opts)
617
+ else
618
+ o << ats[0].first << ': '
619
+ tree_to_flor(ats[1], opts)
620
+ end
621
+ end
622
+
623
+ ctrees.each do |ct|
624
+ o << "\n"
625
+ tree_to_flor(ct, opts.merge(ind: ' ' + i))
626
+ end unless opts[:chop]
627
+ end
628
+ end
629
+
630
+ def c_to_flor(t, opts)
631
+
632
+ o = opts[:o]
633
+
634
+ bs = (t[0] == '_arr') ? %w[ [ ] ] : %w[ { } ]
635
+
636
+ o << bs[0] # opening
637
+
638
+ atts, ctrees = t[1].partition { |ct| is_att_tree?(ct) }
639
+
640
+ ctrees.each_with_index do |ct, i|
641
+ o << ' '
642
+ t_to_flor(ct, opts)
643
+ o << ':' if bs[0] == '{' && i.even?
644
+ end
645
+
646
+ o << (ctrees.any? ? ' ' : '') << bs[1] # closing
647
+ end
648
+
649
+ public
650
+
651
+
523
652
  #
524
653
  # misc
525
654