flor 1.4.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/LICENSE.txt +1 -1
- data/Makefile +4 -4
- data/README.md +1 -1
- data/lib/flor/colours.rb +2 -2
- data/lib/flor/core/node.rb +1 -1
- data/lib/flor/core/procedure.rb +39 -0
- data/lib/flor/flor.rb +1 -1
- data/lib/flor/parser.rb +11 -4
- data/lib/flor/pcore/_apply.rb +1 -1
- data/lib/flor/pcore/on.rb +2 -1
- data/lib/flor/pcore/on_receive.rb +102 -0
- data/lib/flor/punit/concurrence.rb +1 -1
- data/lib/flor/tools/flotojson.rb +28 -2
- data/lib/flor/unit/caller.rb +13 -5
- data/lib/flor/unit/executor.rb +11 -7
- data/lib/flor/unit/ganger.rb +14 -4
- data/lib/flor/unit/logger.rb +2 -1
- data/lib/flor/unit/models/message.rb +2 -0
- data/lib/flor/unit/models/pointer.rb +2 -0
- data/lib/flor/unit/models/timer.rb +2 -0
- data/lib/flor/unit/models/trace.rb +2 -0
- data/lib/flor/unit/models/trap.rb +2 -0
- data/lib/flor/unit/scheduler.rb +21 -21
- data/lib/flor/unit/storage.rb +82 -28
- data/lib/flor/unit/taskers.rb +5 -2
- data/lib/flor.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b28e7de7c950544c32279d8a63917911ae9d12be4154a1bcc0539c8ae343b6d6
|
4
|
+
data.tar.gz: 1838e6d66710983c5adce4dc19b799bed0a34bf5427ee8156c516749d740e703
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f75fd74bd118784e7cf3285bff5f55d4e97c67f4666332712dc9b878c267690247468372ec3970d6cff570f90f235b31ae182279aec87f77d442d7cfa1c6536a
|
7
|
+
data.tar.gz: 8c4b251c6bd1cc514580aae6430dcc70489ca046940e8a9e23104260f48be0a5049ac70310bcecfa3fdb62d00a8e603c644e177ab1db080e38bea04c1c538fa7
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
# CHANGELOG.md
|
3
3
|
|
4
4
|
|
5
|
+
## flor 1.6.0 released 2023-01-13
|
6
|
+
|
7
|
+
* Add #fei to Message, Pointer, Timer, Trace and Trap models
|
8
|
+
* Allow for // comments in Flor language
|
9
|
+
* Call post_task when tasker hands back task
|
10
|
+
|
11
|
+
|
12
|
+
## flor 1.5.0 released 2021-11-24
|
13
|
+
|
14
|
+
* Add storage callbacks `on(:pointers, :any) { do_that }`
|
15
|
+
* Add `on_receive` (and `on receive`)
|
16
|
+
|
17
|
+
|
5
18
|
## flor 1.4.0 released 2021-11-10
|
6
19
|
|
7
20
|
* Add :tree to Execution#to_h
|
data/LICENSE.txt
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
Copyright (c) 2015-
|
2
|
+
Copyright (c) 2015-2023, 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
@@ -1,10 +1,10 @@
|
|
1
1
|
|
2
2
|
## gem tasks ##
|
3
3
|
|
4
|
-
NAME
|
5
|
-
|
6
|
-
VERSION
|
7
|
-
|
4
|
+
NAME != \
|
5
|
+
ruby -e "s = eval(File.read(Dir['*.gemspec'][0])); puts s.name"
|
6
|
+
VERSION != \
|
7
|
+
ruby -e "s = eval(File.read(Dir['*.gemspec'][0])); puts s.version"
|
8
8
|
|
9
9
|
count_lines:
|
10
10
|
find lib -name "*.rb" | xargs cat | ruby -e "p STDIN.readlines.count { |l| l = l.strip; l[0, 1] != '#' && l != '' }"
|
data/README.md
CHANGED
@@ -47,7 +47,7 @@ require 'flor/unit'
|
|
47
47
|
# uncomment to see the flor activity
|
48
48
|
|
49
49
|
sto_uri = 'sqlite://flor_qs.db'
|
50
|
-
sto_uri = 'jdbc:sqlite://flor_qs.db' if RUBY_PLATFORM.match(/java/)
|
50
|
+
sto_uri = 'jdbc:sqlite://flor_qs.db' if RUBY_PLATFORM.match?(/java/)
|
51
51
|
|
52
52
|
flor = Flor::Unit.new(loader: Flor::HashLoader, sto_uri: sto_uri)
|
53
53
|
# instantiate flor unit
|
data/lib/flor/colours.rb
CHANGED
@@ -27,7 +27,7 @@ module Flor
|
|
27
27
|
class Colours
|
28
28
|
|
29
29
|
Flor::COLS.each do |k, v|
|
30
|
-
if v.match(/\A\d/)
|
30
|
+
if v.match(/\A\d/) # Ruby 2.3 doesn't have String#match?
|
31
31
|
class_eval(%{
|
32
32
|
def #{k}(s=nil)
|
33
33
|
s ? "[#{v}m" + s + "[0;0m" : "[#{v}m"
|
@@ -42,7 +42,7 @@ module Flor
|
|
42
42
|
class NoColours
|
43
43
|
|
44
44
|
Flor::COLS.each do |k, v|
|
45
|
-
if v.match(/\A\d/)
|
45
|
+
if v.match(/\A\d/) # Ruby 2.3 doesn't have String#match?
|
46
46
|
class_eval("def #{k}(s=''); s; end")
|
47
47
|
else
|
48
48
|
class_eval("alias #{k} #{v}")
|
data/lib/flor/core/node.rb
CHANGED
@@ -88,7 +88,7 @@ class Flor::Node
|
|
88
88
|
def domain; Flor.domain(@execution['exid']); end
|
89
89
|
|
90
90
|
def point; @message['point']; end
|
91
|
-
def from; @message['from']; end
|
91
|
+
def from; @from || @message['from']; end
|
92
92
|
|
93
93
|
def cnodes; @node['cnodes']; end
|
94
94
|
def cnodes_any?; cnodes && cnodes.any?; end
|
data/lib/flor/core/procedure.rb
CHANGED
@@ -381,8 +381,17 @@ class Flor::Procedure < Flor::Node
|
|
381
381
|
|
382
382
|
receive_when_ended
|
383
383
|
|
384
|
+
elsif should_apply_on_receive?
|
385
|
+
|
386
|
+
apply_on_receive
|
387
|
+
|
384
388
|
else
|
385
389
|
|
390
|
+
orn = @node['on_receive_nid']
|
391
|
+
@from = orn[1] if orn && orn[0] == from
|
392
|
+
#
|
393
|
+
# in order to move on to the next child...
|
394
|
+
|
386
395
|
receive
|
387
396
|
end
|
388
397
|
end
|
@@ -982,6 +991,36 @@ class Flor::Procedure < Flor::Node
|
|
982
991
|
|
983
992
|
[]
|
984
993
|
end
|
994
|
+
|
995
|
+
def should_apply_on_receive?
|
996
|
+
|
997
|
+
return false if @message['from_on'] == 'receive'
|
998
|
+
#
|
999
|
+
# no, since the message comes from an on_receive...
|
1000
|
+
# how about nested on_receives?
|
1001
|
+
|
1002
|
+
orc = @node['on_receive']
|
1003
|
+
return false if orc.nil? || orc.empty?
|
1004
|
+
|
1005
|
+
orn = @node['on_receive_nid']
|
1006
|
+
return false if orn && orn[0] == from
|
1007
|
+
|
1008
|
+
true
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
def apply_on_receive
|
1012
|
+
|
1013
|
+
determine_fcid_and_ncid
|
1014
|
+
|
1015
|
+
args = [
|
1016
|
+
[ 'msg', @message ],
|
1017
|
+
[ 'fcid', @fcid ] ]
|
1018
|
+
|
1019
|
+
ms = apply(@node['on_receive'][0][1], args, tree[2])
|
1020
|
+
@node['on_receive_nid'] = [ ms[0]['nid'], from ]
|
1021
|
+
|
1022
|
+
ms
|
1023
|
+
end
|
985
1024
|
end
|
986
1025
|
|
987
1026
|
|
data/lib/flor/flor.rb
CHANGED
data/lib/flor/parser.rb
CHANGED
@@ -6,6 +6,9 @@ module Flor
|
|
6
6
|
|
7
7
|
#Raabro.pp(Flor::Parser.parse(input, debug: 2), colours: true)
|
8
8
|
#Raabro.pp(Flor::Parser.parse(input, debug: 3), colours: true)
|
9
|
+
#
|
10
|
+
# turn one or the other when debugging the parser...
|
11
|
+
|
9
12
|
opts = fname if fname.is_a?(Hash) && opts.empty?
|
10
13
|
|
11
14
|
if r = Flor::Parser.parse(input, opts)
|
@@ -49,7 +52,7 @@ module Flor
|
|
49
52
|
def semicolon(i); str(nil, i, ';'); end
|
50
53
|
def comma(i); str(nil, i, ','); end
|
51
54
|
def dquote(i); str(nil, i, '"'); end
|
52
|
-
def slash(i);
|
55
|
+
def slash(i); rex(nil, i, /\/(?!\/)/); end
|
53
56
|
def dollar(i); str(nil, i, '$'); end
|
54
57
|
def pipepipe(i); str(nil, i, '||'); end
|
55
58
|
|
@@ -95,7 +98,11 @@ module Flor
|
|
95
98
|
seq(nil, i, :dot, :rf_symbol)
|
96
99
|
end
|
97
100
|
def rf_index(i); alt(nil, i, :rf_dot_idx, :rf_sqa_idx); end
|
98
|
-
|
101
|
+
#
|
102
|
+
def rf_symbol(i)
|
103
|
+
rex(:refsym, i, /([^.:;| \b\f\n\r\t"',()\[\]{}#\\\/]|\/(?!\/))+/)
|
104
|
+
# anything but... a slash is ok, but not a double slash...
|
105
|
+
end
|
99
106
|
#
|
100
107
|
def reference(i); seq(:ref, i, :rf_symbol, :rf_index, '*'); end
|
101
108
|
|
@@ -165,7 +172,7 @@ module Flor
|
|
165
172
|
}x)
|
166
173
|
end
|
167
174
|
|
168
|
-
def comment(i); rex(nil, i,
|
175
|
+
def comment(i); rex(nil, i, /(#|\/\/)[^\r\n]*/); end
|
169
176
|
|
170
177
|
def eol(i); seq(nil, i, :wstar, :comment, '?', :rnstar); end
|
171
178
|
def eol_wstar(i); seq(nil, i, :wstar, :comment, '?', :rnstar, :wstar); end
|
@@ -210,7 +217,7 @@ module Flor
|
|
210
217
|
# %w[ equ == != <> ], %w[ lgt < > <= >= ], %w[ sum + - ], %w[ prd * / % ],
|
211
218
|
|
212
219
|
def ssmod(i); str(:sop, i, /%/); end
|
213
|
-
def ssprd(i); rex(:sop, i, /
|
220
|
+
def ssprd(i); rex(:sop, i, /(\*|\/(?!\/))/); end
|
214
221
|
def sssum(i); rex(:sop, i, /[+-]/); end
|
215
222
|
def sslgt(i); rex(:sop, i, /(<=?|>=?)/); end
|
216
223
|
def ssequ(i); rex(:sop, i, /(==?|!=|<>)/); end
|
data/lib/flor/pcore/_apply.rb
CHANGED
@@ -99,7 +99,7 @@ class Flor::Pro::UnderscoreApply < Flor::Procedure
|
|
99
99
|
|
100
100
|
params.each do |param_key, param_tree|
|
101
101
|
next if param_tree[0] == '_ref'
|
102
|
-
arg_i = args.index { |arg_key,
|
102
|
+
arg_i = args.index { |arg_key, _| arg_key == param_key }
|
103
103
|
next unless arg_i
|
104
104
|
arg_key, arg_val = args.delete_at(arg_i)
|
105
105
|
seen << arg_key
|
data/lib/flor/pcore/on.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
|
3
4
|
class Flor::Pro::On < Flor::Macro
|
4
5
|
#
|
5
6
|
# Catches signals or errors.
|
@@ -132,7 +133,7 @@ class Flor::Pro::On < Flor::Macro
|
|
132
133
|
|
133
134
|
protected
|
134
135
|
|
135
|
-
CATCHES = %w[ error cancel timeout ].freeze
|
136
|
+
CATCHES = %w[ error cancel timeout receive ].freeze
|
136
137
|
|
137
138
|
def find_catch
|
138
139
|
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
class Flor::Pro::OnReceive < Flor::Procedure
|
5
|
+
#
|
6
|
+
# Binds a function to the parent node, the function will be called each time
|
7
|
+
# the parent node "receives".
|
8
|
+
#
|
9
|
+
# ```
|
10
|
+
# set l []
|
11
|
+
# sequence
|
12
|
+
# on_receive (def msg \ push l 'a')
|
13
|
+
# push l 0
|
14
|
+
# push l 1
|
15
|
+
# push l 2
|
16
|
+
# ```
|
17
|
+
# will result in the variable `l` holding `[ 0, 'a', 1, 'a', 2, 'a' ]`.
|
18
|
+
#
|
19
|
+
# ```
|
20
|
+
# set l []
|
21
|
+
# sequence
|
22
|
+
# push l 0
|
23
|
+
# on_receive (def msg \ push l 'a')
|
24
|
+
# push l 1
|
25
|
+
# push l 2
|
26
|
+
# ```
|
27
|
+
# will result in the variable `l` holding `[ 0, 1, 'a', 2, 'a' ]`.
|
28
|
+
#
|
29
|
+
# It's meant to play well with a cursor:
|
30
|
+
# ```
|
31
|
+
# set l []
|
32
|
+
# cursor
|
33
|
+
# on_receive (def \ break _ if l[-1] == 1)
|
34
|
+
# push l 0
|
35
|
+
# push l 1
|
36
|
+
# push l 2
|
37
|
+
# push l 'z'
|
38
|
+
# ```
|
39
|
+
# will result in the variable `l` holding `[ 0, 1, 'z' ]`.
|
40
|
+
#
|
41
|
+
#
|
42
|
+
# ## arguments to the on_receive function
|
43
|
+
#
|
44
|
+
# `msg` and `fcid` (from child id) are passed to the function
|
45
|
+
# ```
|
46
|
+
# set l []
|
47
|
+
# cursor
|
48
|
+
# on_receive (def msg, fcid \ push l [ msg.from, fcid ])
|
49
|
+
# push l 0
|
50
|
+
# push l 1
|
51
|
+
# push l 2
|
52
|
+
# ```
|
53
|
+
# will result in the variable `l` holding
|
54
|
+
# `[ 0, [ '0_1_1', 1 ], 1, [ '0_1_2', 2 ], 2, [ '0_1_3', 3 ] ]`.
|
55
|
+
#
|
56
|
+
#
|
57
|
+
# ## on_receive and on receive
|
58
|
+
#
|
59
|
+
# A "lighter" notation is available (it's translated automatically to a
|
60
|
+
# `on_receive`):
|
61
|
+
# ```
|
62
|
+
# set l []
|
63
|
+
# cursor
|
64
|
+
# on receive
|
65
|
+
# push l $msg.from
|
66
|
+
# break _ if l.-1 == 1
|
67
|
+
# push l 0
|
68
|
+
# push l 1
|
69
|
+
# push l 2
|
70
|
+
# ```
|
71
|
+
#
|
72
|
+
# Please note the `$msg` variable made available to the `on receive` block.
|
73
|
+
#
|
74
|
+
#
|
75
|
+
# ## concurrence and on_receive
|
76
|
+
#
|
77
|
+
# Please not that `concurrence` has its own `on_receive` with a slightly
|
78
|
+
# different behaviour.
|
79
|
+
|
80
|
+
name 'on_receive'
|
81
|
+
|
82
|
+
def pre_execute
|
83
|
+
|
84
|
+
unatt_unkeyed_children
|
85
|
+
|
86
|
+
@node['rets'] = []
|
87
|
+
end
|
88
|
+
|
89
|
+
def receive_last
|
90
|
+
|
91
|
+
prc = @node['rets'].find { |r| Flor.is_func_tree?(r) }
|
92
|
+
|
93
|
+
store_on(:receive, prc)
|
94
|
+
|
95
|
+
ms = super
|
96
|
+
|
97
|
+
ms.first['from_on'] = 'receive'
|
98
|
+
|
99
|
+
ms
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
data/lib/flor/tools/flotojson.rb
CHANGED
@@ -16,7 +16,16 @@ if (ARGV & [ '-h', '--help']).any?
|
|
16
16
|
puts " turns a flor .flo process definition to its tree representation"
|
17
17
|
puts
|
18
18
|
puts " flags:"
|
19
|
-
puts " --pp
|
19
|
+
puts " --pp pretty prints instead of dumping as JSON"
|
20
|
+
puts
|
21
|
+
puts " --pj"
|
22
|
+
puts " --jp pretty prints the JSON output"
|
23
|
+
puts
|
24
|
+
puts " -y"
|
25
|
+
puts " -yaml dumps as YAML"
|
26
|
+
puts
|
27
|
+
puts " -h"
|
28
|
+
puts " --help prints this help message"
|
20
29
|
puts
|
21
30
|
exit 0
|
22
31
|
end
|
@@ -53,11 +62,28 @@ end
|
|
53
62
|
# end
|
54
63
|
|
55
64
|
fname = files.first
|
56
|
-
|
65
|
+
|
66
|
+
content =
|
67
|
+
if fname
|
68
|
+
abort("File #{fname.inspect} not found") unless File.exist?(fname)
|
69
|
+
File.read(fname)
|
70
|
+
else
|
71
|
+
STDIN.read
|
72
|
+
end
|
73
|
+
|
57
74
|
tree = Flor.parse(content, fname, {})
|
58
75
|
|
59
76
|
if flags['--pp']
|
60
77
|
pp tree
|
78
|
+
elsif flags['--jp'] || flags['--pj']
|
79
|
+
puts(
|
80
|
+
JSON.pretty_generate(tree)
|
81
|
+
.gsub(/\[\s+/, '[ ')
|
82
|
+
.gsub(/\]\s+/, ']')
|
83
|
+
.gsub(/,\s+(\d+)\s+\]/, ', \1]')
|
84
|
+
)
|
85
|
+
elsif flags['-y'] || flags['--yaml']
|
86
|
+
puts YAML.dump(tree)
|
61
87
|
else
|
62
88
|
puts JSON.dump(tree)
|
63
89
|
end
|
data/lib/flor/unit/caller.rb
CHANGED
@@ -110,10 +110,16 @@ module Flor
|
|
110
110
|
pt = message['point']
|
111
111
|
|
112
112
|
ms = [ "call_#{pt}", "on_#{pt}", :on_message, :on, pt ]
|
113
|
-
|
113
|
+
case pt
|
114
|
+
when 'detask' then ms = ms + [ :on_cancel, :cancel ]
|
115
|
+
when 'return' then ms = [ :on_return, :return, :post_task ] # /!\
|
116
|
+
end
|
114
117
|
|
115
118
|
m = ms.find { |mm| o.respond_to?(mm) }
|
116
119
|
|
120
|
+
return [ message ] if pt == 'return' && ! m
|
121
|
+
# don't call if :post_task not present
|
122
|
+
|
117
123
|
fail(
|
118
124
|
"#{k.class.to_s.downcase} #{k} doesn't respond to " +
|
119
125
|
ms[0..-2].collect { |e| "##{e}" }.join(', ') + ", or ##{ms[-1]}"
|
@@ -316,10 +322,12 @@ module Flor
|
|
316
322
|
|
317
323
|
def to_messages(o)
|
318
324
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
325
|
+
if Flor.is_array_of_messages?(o)
|
326
|
+
o
|
327
|
+
elsif Flor.is_message?(o)
|
328
|
+
[ o ]
|
329
|
+
else
|
330
|
+
[]
|
323
331
|
end
|
324
332
|
end
|
325
333
|
|
data/lib/flor/unit/executor.rb
CHANGED
@@ -48,7 +48,7 @@ module Flor
|
|
48
48
|
|
49
49
|
protected
|
50
50
|
|
51
|
-
CLOSING_POINTS = %w[ task terminated ceased ]
|
51
|
+
CLOSING_POINTS = %w[ task terminated ceased ].freeze
|
52
52
|
#
|
53
53
|
# point for messages that, after consumption, are conserved
|
54
54
|
# in the execution's "closing_messages" array
|
@@ -160,14 +160,18 @@ module Flor
|
|
160
160
|
def return(message)
|
161
161
|
|
162
162
|
n = @execution['nodes'][message['nid']] || {}
|
163
|
-
|
164
|
-
c = m['cause']
|
163
|
+
c = (n['message'] || {})['cause']
|
165
164
|
|
166
|
-
|
167
|
-
|
168
|
-
|
165
|
+
ms =
|
166
|
+
if n['task']
|
167
|
+
@unit.ganger.task(self, message)
|
168
|
+
else
|
169
|
+
[ message.dup ]
|
170
|
+
end
|
169
171
|
|
170
|
-
|
172
|
+
ms.each { |m|
|
173
|
+
m['point'] = 'receive'
|
174
|
+
m['cause'] = c if c }
|
171
175
|
end
|
172
176
|
|
173
177
|
def schedule(message)
|
data/lib/flor/unit/ganger.rb
CHANGED
@@ -47,16 +47,14 @@ module Flor
|
|
47
47
|
def task(executor, message)
|
48
48
|
|
49
49
|
domain = message['exid'].split('-', 2).first
|
50
|
-
tname = message['tasker']
|
50
|
+
#tname = message['tasker']
|
51
|
+
tname = determine_tasker_name(executor, message)
|
51
52
|
|
52
53
|
tconf =
|
53
54
|
( ! message['routed'] &&
|
54
55
|
(@unit.loader.tasker(domain, 'ganger', message) ||
|
55
56
|
@unit.loader.tasker(domain, 'tasker', message))) ||
|
56
57
|
@unit.loader.tasker(domain, tname, message)
|
57
|
-
#puts "=" * 80
|
58
|
-
#pp tconf
|
59
|
-
#puts "=" * 80
|
60
58
|
|
61
59
|
fail ArgumentError.new(
|
62
60
|
"tasker #{tname.inspect} not found"
|
@@ -66,6 +64,7 @@ module Flor
|
|
66
64
|
|
67
65
|
points = [ nil, message['point'] ]
|
68
66
|
points << 'detask' if points.include?('cancel')
|
67
|
+
points << 'task' if points.include?('return')
|
69
68
|
|
70
69
|
tconf = tconf.find { |h| points.include?(h['point']) }
|
71
70
|
end
|
@@ -154,6 +153,17 @@ module Flor
|
|
154
153
|
|
155
154
|
vars
|
156
155
|
end
|
156
|
+
|
157
|
+
def determine_tasker_name(executor, message)
|
158
|
+
|
159
|
+
tname = message['tasker']
|
160
|
+
|
161
|
+
return tname if tname
|
162
|
+
|
163
|
+
n = executor.node(message)
|
164
|
+
|
165
|
+
n['task']['tasker']
|
166
|
+
end
|
157
167
|
end
|
158
168
|
end
|
159
169
|
|
data/lib/flor/unit/logger.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
|
3
4
|
module Flor
|
4
5
|
|
5
6
|
# TODO ::Logger has a formatting callback
|
@@ -11,7 +12,7 @@ module Flor
|
|
11
12
|
|
12
13
|
# NB: logger configuration entries start with "log_"
|
13
14
|
|
14
|
-
LEVELS_I = %w[ DEBUG INFO WARN ERROR FATAL UNKNOWN ]
|
15
|
+
LEVELS_I = %w[ DEBUG INFO WARN ERROR FATAL UNKNOWN ].freeze
|
15
16
|
|
16
17
|
def initialize(unit)
|
17
18
|
|
@@ -29,6 +29,8 @@ module Flor
|
|
29
29
|
# # we don't care, pointers are cleaned anyway when the flow dies
|
30
30
|
#end
|
31
31
|
|
32
|
+
def fei; [ exid, nid ].join('-'); end
|
33
|
+
|
32
34
|
# If the pointer is a "var" pointer, returns the full value
|
33
35
|
# for the variable, as found in the execution's node "0".
|
34
36
|
#
|
data/lib/flor/unit/scheduler.rb
CHANGED
@@ -113,27 +113,6 @@ module Flor
|
|
113
113
|
@ganger.shutdown
|
114
114
|
end
|
115
115
|
|
116
|
-
def on_start_exc(e)
|
117
|
-
|
118
|
-
io = StringIO.new
|
119
|
-
|
120
|
-
head, kind =
|
121
|
-
e.is_a?(StandardError) ? [ '=sch', 'error' ] : [ '!sch', 'exception' ]
|
122
|
-
thr = Thread.current
|
123
|
-
|
124
|
-
t = head[0, 2] + Time.now.to_f.to_s.split('.').last
|
125
|
-
io.puts ' /' + t + ' ' + head * 17
|
126
|
-
io.puts " |#{t} + in #{self.class}#start"
|
127
|
-
io.puts " |#{t} db: #{@storage.db.class} #{@storage.db.object_id}"
|
128
|
-
io.puts " |#{t} thread: t#{thr.object_id} #{thr.inspect}"
|
129
|
-
io.puts " |#{t} #{kind}: #{e.inspect}"
|
130
|
-
io.puts " |#{t} backtrace:"
|
131
|
-
e.backtrace.each { |l| io.puts "|#{t} #{l}" }
|
132
|
-
io.puts ' \\' + t + ' ' + (head * 17) + ' .'
|
133
|
-
|
134
|
-
io.string
|
135
|
-
end
|
136
|
-
|
137
116
|
def start
|
138
117
|
|
139
118
|
# TODO heartbeat, every x minutes, when idle, log something
|
@@ -557,6 +536,27 @@ module Flor
|
|
557
536
|
|
558
537
|
protected
|
559
538
|
|
539
|
+
def on_start_exc(e)
|
540
|
+
|
541
|
+
io = StringIO.new
|
542
|
+
|
543
|
+
head, kind =
|
544
|
+
e.is_a?(StandardError) ? [ '=sch', 'error' ] : [ '!sch', 'exception' ]
|
545
|
+
thr = Thread.current
|
546
|
+
|
547
|
+
t = head[0, 2] + Time.now.to_f.to_s.split('.').last
|
548
|
+
io.puts ' /' + t + ' ' + head * 17
|
549
|
+
io.puts " |#{t} + in #{self.class}#start"
|
550
|
+
io.puts " |#{t} db: #{@storage.db.class} #{@storage.db.object_id}"
|
551
|
+
io.puts " |#{t} thread: t#{thr.object_id} #{thr.inspect}"
|
552
|
+
io.puts " |#{t} #{kind}: #{e.inspect}"
|
553
|
+
io.puts " |#{t} backtrace:"
|
554
|
+
e.backtrace.each { |l| io.puts "|#{t} #{l}" }
|
555
|
+
io.puts ' \\' + t + ' ' + (head * 17) + ' .'
|
556
|
+
|
557
|
+
io.string
|
558
|
+
end
|
559
|
+
|
560
560
|
def extract_dump_and_load_filters(opts)
|
561
561
|
|
562
562
|
o = lambda { |k| v = opts[k] || opts["#{k}s".to_sym]; v ? Array(v) : nil }
|
data/lib/flor/unit/storage.rb
CHANGED
@@ -16,7 +16,7 @@ module Flor
|
|
16
16
|
:content
|
17
17
|
].freeze
|
18
18
|
|
19
|
-
attr_reader :unit, :db, :models
|
19
|
+
attr_reader :unit, :db, :models, :callbacks
|
20
20
|
|
21
21
|
attr_reader :mutex
|
22
22
|
# might be useful for some implementations
|
@@ -31,6 +31,8 @@ module Flor
|
|
31
31
|
@archive = @unit.conf['sto_archive']
|
32
32
|
@mutex = @unit.conf['sto_sync'] ? Mutex.new : nil
|
33
33
|
|
34
|
+
@callbacks = {}
|
35
|
+
|
34
36
|
connect
|
35
37
|
end
|
36
38
|
|
@@ -191,6 +193,8 @@ module Flor
|
|
191
193
|
mtime: now,
|
192
194
|
munit: u)
|
193
195
|
|
196
|
+
callback(:executions, :update, id)
|
197
|
+
|
194
198
|
else
|
195
199
|
|
196
200
|
exe['id'] =
|
@@ -205,6 +209,8 @@ module Flor
|
|
205
209
|
cunit: u,
|
206
210
|
munit: u)
|
207
211
|
.to_i
|
212
|
+
|
213
|
+
callback(:executions, :insert, exe['id'])
|
208
214
|
end
|
209
215
|
|
210
216
|
remove_nodes(exe, status, now)
|
@@ -418,26 +424,29 @@ module Flor
|
|
418
424
|
now = Flor.tstamp
|
419
425
|
u = @unit.identifier
|
420
426
|
|
421
|
-
|
427
|
+
id =
|
428
|
+
synchronize do
|
422
429
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
430
|
+
@db[:flor_timers]
|
431
|
+
.insert(
|
432
|
+
domain: Flor.domain(message['exid']),
|
433
|
+
exid: message['exid'],
|
434
|
+
nid: message['nid'],
|
435
|
+
onid: message['onid'] || message['nid'],
|
436
|
+
bnid: message['nid'],
|
437
|
+
type: type,
|
438
|
+
schedule: string,
|
439
|
+
ntime: next_time,
|
440
|
+
content: to_blob(message),
|
441
|
+
count: 0,
|
442
|
+
status: 'active',
|
443
|
+
ctime: now,
|
444
|
+
mtime: now,
|
445
|
+
cunit: u,
|
446
|
+
munit: u)
|
447
|
+
end
|
448
|
+
|
449
|
+
callback(:timers, :insert, id)
|
441
450
|
|
442
451
|
@unit.wake_up
|
443
452
|
|
@@ -502,6 +511,8 @@ module Flor
|
|
502
511
|
munit: u)
|
503
512
|
end
|
504
513
|
|
514
|
+
callback(:traps, :insert, id)
|
515
|
+
|
505
516
|
traps[id]
|
506
517
|
|
507
518
|
rescue => err
|
@@ -548,6 +559,21 @@ module Flor
|
|
548
559
|
nil
|
549
560
|
end
|
550
561
|
|
562
|
+
def on(key, actions=[], &block)
|
563
|
+
|
564
|
+
as =
|
565
|
+
case actions
|
566
|
+
when :any, 'any' then []
|
567
|
+
when Array then actions
|
568
|
+
when Symbol then [ actions ]
|
569
|
+
when String then actions.split(/\s*[;,]\s*/)
|
570
|
+
else []
|
571
|
+
end
|
572
|
+
.collect(&:to_sym)
|
573
|
+
|
574
|
+
(@callbacks[key] ||= []) << [ as, block ]
|
575
|
+
end
|
576
|
+
|
551
577
|
protected
|
552
578
|
|
553
579
|
def migration_table_and_column(opts={})
|
@@ -640,10 +666,11 @@ module Flor
|
|
640
666
|
def reschedule_timer(t)
|
641
667
|
|
642
668
|
w = { id: t.id.to_i, status: 'active', mtime: t.mtime, munit: t.munit }
|
669
|
+
r = nil
|
643
670
|
|
644
671
|
if t.type != 'at' && t.type != 'in'
|
645
672
|
|
646
|
-
@db[:flor_timers]
|
673
|
+
r = @db[:flor_timers]
|
647
674
|
.where(w)
|
648
675
|
.update(
|
649
676
|
count: t.count.to_i + 1,
|
@@ -652,9 +679,11 @@ module Flor
|
|
652
679
|
mtime: Flor.tstamp,
|
653
680
|
munit: @unit.identifier)
|
654
681
|
|
682
|
+
callback(:timers, :update, w, t)
|
683
|
+
|
655
684
|
elsif @archive
|
656
685
|
|
657
|
-
@db[:flor_timers]
|
686
|
+
r = @db[:flor_timers]
|
658
687
|
.where(w)
|
659
688
|
.update(
|
660
689
|
count: t.count.to_i + 1,
|
@@ -662,12 +691,18 @@ module Flor
|
|
662
691
|
mtime: Flor.tstamp,
|
663
692
|
munit: @unit.identifier)
|
664
693
|
|
694
|
+
callback(:timers, :update, w, t)
|
695
|
+
|
665
696
|
else
|
666
697
|
|
667
|
-
@db[:flor_timers]
|
698
|
+
r = @db[:flor_timers]
|
668
699
|
.where(w)
|
669
700
|
.delete
|
701
|
+
|
702
|
+
callback(:timers, :delete, w, t)
|
670
703
|
end
|
704
|
+
|
705
|
+
r
|
671
706
|
end
|
672
707
|
|
673
708
|
def remove_nodes(exe, status, now)
|
@@ -787,6 +822,8 @@ module Flor
|
|
787
822
|
.import(
|
788
823
|
POINTER_COLUMNS,
|
789
824
|
pointers)
|
825
|
+
|
826
|
+
callback(:pointers, :update, exid)
|
790
827
|
end
|
791
828
|
|
792
829
|
#def pointer_columns
|
@@ -835,6 +872,23 @@ module Flor
|
|
835
872
|
.inject([]) { |a, elt| a << [ a.last, elt ].compact.join('.'); a }
|
836
873
|
end
|
837
874
|
|
875
|
+
def callback(table, action, *rest)
|
876
|
+
|
877
|
+
(@callbacks[table] || [])
|
878
|
+
.each { |as, block|
|
879
|
+
call_back(block, table, action, *rest) \
|
880
|
+
if as.empty? || as.include?(action) }
|
881
|
+
end
|
882
|
+
|
883
|
+
def call_back(block, table, action, *rest)
|
884
|
+
|
885
|
+
block.call(
|
886
|
+
*(
|
887
|
+
block.arity < 0 ?
|
888
|
+
[ table, action, *rest ] :
|
889
|
+
[ table, action, *rest ][0, block.arity]))
|
890
|
+
end
|
891
|
+
|
838
892
|
class DbLogger
|
839
893
|
|
840
894
|
def initialize(unit); @unit = unit; end
|
@@ -854,11 +908,11 @@ module Flor
|
|
854
908
|
fail ArgumentError.new("no 'sto_uri' conf, cannot connect to db") \
|
855
909
|
unless uri
|
856
910
|
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
911
|
+
begin
|
912
|
+
Kernel.const_get(uri)
|
913
|
+
rescue NameError
|
914
|
+
Sequel.connect(uri)
|
915
|
+
end
|
862
916
|
end
|
863
917
|
|
864
918
|
def connect
|
data/lib/flor/unit/taskers.rb
CHANGED
@@ -169,9 +169,12 @@ module Flor
|
|
169
169
|
|
170
170
|
pt = @message['point']
|
171
171
|
|
172
|
-
ms = [ "post_#{pt}" ]; ms << :post_cancel if pt == 'detask'
|
172
|
+
#ms = [ "post_#{pt}" ]; ms << :post_cancel if pt == 'detask'
|
173
|
+
#call_one_of(ms)
|
173
174
|
#
|
174
|
-
|
175
|
+
# :post_task is called by, well, the caller
|
176
|
+
#
|
177
|
+
call_one_of([ :post_detask, :post_cancel ]) if pt == 'detask'
|
175
178
|
|
176
179
|
msg = derive_message(message)
|
177
180
|
|
data/lib/flor.rb
CHANGED
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.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mettraux
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: munemo
|
@@ -204,6 +204,7 @@ files:
|
|
204
204
|
- lib/flor/pcore/on.rb
|
205
205
|
- lib/flor/pcore/on_cancel.rb
|
206
206
|
- lib/flor/pcore/on_error.rb
|
207
|
+
- lib/flor/pcore/on_receive.rb
|
207
208
|
- lib/flor/pcore/push.rb
|
208
209
|
- lib/flor/pcore/rand.rb
|
209
210
|
- lib/flor/pcore/range.rb
|
@@ -289,7 +290,7 @@ metadata:
|
|
289
290
|
mailing_list_uri: https://groups.google.com/forum/#!forum/floraison
|
290
291
|
homepage_uri: https://github.com/floraison/flor
|
291
292
|
source_code_uri: https://github.com/floraison/flor
|
292
|
-
post_install_message:
|
293
|
+
post_install_message:
|
293
294
|
rdoc_options: []
|
294
295
|
require_paths:
|
295
296
|
- lib
|
@@ -304,8 +305,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
304
305
|
- !ruby/object:Gem::Version
|
305
306
|
version: '0'
|
306
307
|
requirements: []
|
307
|
-
rubygems_version: 3.
|
308
|
-
signing_key:
|
308
|
+
rubygems_version: 3.1.6
|
309
|
+
signing_key:
|
309
310
|
specification_version: 4
|
310
311
|
summary: A Ruby workflow engine
|
311
312
|
test_files: []
|