cpee 2.0.6 → 2.0.13
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 +4 -4
- data/cockpit/config.json +3 -0
- data/cockpit/css/track.css +17 -6
- data/cockpit/css/ui.css +6 -2
- data/cockpit/css/wfadaptor.css +1 -1
- data/cockpit/edit.html +1 -0
- data/cockpit/index.html +2 -2
- data/cockpit/js/instance.js +75 -55
- data/cockpit/js/track.js +10 -0
- data/cockpit/js/ui.js +47 -16
- data/cockpit/templates/Track Test Local.xml +82 -0
- data/cockpit/templates/Track Test.xml +82 -0
- data/cockpit/templates/instantiate.local/Take_Sub.xml +59 -0
- data/cockpit/templates/instantiate/Take_Perf.xml +46 -0
- data/cockpit/templates/instantiate/Take_Sub.xml +58 -0
- data/cockpit/templates/instantiate/Take_X.xml +48 -0
- data/cockpit/themes/compact/rngs/call.rng +5 -0
- data/cockpit/themes/compact/rngs/callmanipulate.rng +6 -1
- data/cockpit/themes/compact/rngs/loop.rng +1 -1
- data/cockpit/themes/compact/rngs/parallel.rng +1 -1
- data/cockpit/themes/default/rngs/call.rng +5 -0
- data/cockpit/themes/default/rngs/callmanipulate.rng +6 -1
- data/cockpit/themes/default/rngs/loop.rng +1 -1
- data/cockpit/themes/default/rngs/parallel.rng +1 -1
- data/cockpit/themes/extended/rngs/call.rng +5 -0
- data/cockpit/themes/extended/rngs/callmanipulate.rng +6 -1
- data/cockpit/themes/extended/rngs/loop.rng +1 -1
- data/cockpit/themes/extended/rngs/parallel.rng +1 -1
- data/cockpit/themes/extended/theme.js +4 -0
- data/cockpit/themes/model/theme.js +1 -1
- data/cockpit/themes/packed/rngs/call.rng +5 -0
- data/cockpit/themes/packed/rngs/callmanipulate.rng +6 -1
- data/cockpit/themes/packed/rngs/loop.rng +1 -1
- data/cockpit/themes/packed/rngs/parallel.rng +1 -1
- data/cockpit/themes/preset/rngs/call.rng +5 -0
- data/cockpit/themes/preset/rngs/callmanipulate.rng +6 -1
- data/cockpit/themes/preset/rngs/loop.rng +1 -1
- data/cockpit/themes/preset/rngs/parallel.rng +1 -1
- data/cockpit/track.html +37 -8
- data/cpee.gemspec +3 -3
- data/lib/cpee/implementation.rb +15 -6
- data/lib/cpee/implementation_notifications.rb +80 -51
- data/lib/cpee/implementation_properties.rb +5 -2
- data/lib/cpee/persistence.rb +3 -0
- data/server/handlerwrappers/default.rb +3 -0
- data/server/routing/forward-events.rb +2 -1
- data/server/routing/forward-votes.rb +1 -1
- data/server/server.conf +4 -0
- data/tools/cpee +17 -9
- metadata +17 -10
- data/cockpit/templates/convert_cpee2.rb +0 -15
- data/cockpit/themes/convert_cpee2.rb +0 -8
@@ -241,7 +241,7 @@ function WFAdaptorManifestation(adaptor) {
|
|
241
241
|
'label': function(node){
|
242
242
|
var ret;
|
243
243
|
if ($('> url',$(node).children('parameters').children('arguments')).length > 0) {
|
244
|
-
ret = [ { column: 'Label', value:
|
244
|
+
ret = [ { column: 'Label', value: $('> label',$(node).children('parameters')).text().replace(/^['"]/,'').replace(/['"]$/,'') + ' <a target="blank_" href="' + $('> url',$(node).children('parameters').children('arguments')).text() + '"></a>' } ];
|
245
245
|
} else {
|
246
246
|
ret = [ { column: 'Label', value: $('> label',$(node).children('parameters')).text().replace(/^['"]/,'').replace(/['"]$/,'') } ];
|
247
247
|
}
|
@@ -89,6 +89,11 @@
|
|
89
89
|
</zeroOrMore>
|
90
90
|
</element>
|
91
91
|
</element>
|
92
|
+
<element name="report" rngui:header="Reporting Annotation" rngui:fold="closed">
|
93
|
+
<element name="url" rngui:label='HTML Snippet'>
|
94
|
+
<data type="string" rngui:label="url to report snippet"/>
|
95
|
+
</element>
|
96
|
+
</element>
|
92
97
|
</element>
|
93
98
|
<element name="annotations" rngui:header="Annotations">
|
94
99
|
<element name="_timing" rngui:header="Timing" rngui:fold="closed">
|
@@ -89,6 +89,11 @@
|
|
89
89
|
</zeroOrMore>
|
90
90
|
</element>
|
91
91
|
</element>
|
92
|
+
<element name="report" rngui:header="Reporting Annotation" rngui:fold="closed">
|
93
|
+
<element name="url" rngui:label='HTML Snippet'>
|
94
|
+
<data type="string" rngui:label="url to report snippet"/>
|
95
|
+
</element>
|
96
|
+
</element>
|
92
97
|
</element>
|
93
98
|
<element name="code" rngui:header="Implementation">
|
94
99
|
<element name="prepare" rngui:header="Prepare" rngui:label="Code" rngui:fold="closed_conditional">
|
@@ -137,4 +142,4 @@
|
|
137
142
|
</element>
|
138
143
|
</element>
|
139
144
|
</element>
|
140
|
-
</element>
|
145
|
+
</element>
|
@@ -89,6 +89,11 @@
|
|
89
89
|
</zeroOrMore>
|
90
90
|
</element>
|
91
91
|
</element>
|
92
|
+
<element name="report" rngui:header="Reporting Annotation" rngui:fold="closed">
|
93
|
+
<element name="url" rngui:label='HTML Snippet'>
|
94
|
+
<data type="string" rngui:label="url to report snippet"/>
|
95
|
+
</element>
|
96
|
+
</element>
|
92
97
|
</element>
|
93
98
|
<element name="annotations" rngui:header="Annotations">
|
94
99
|
<element name="_timing" rngui:header="Timing" rngui:fold="closed">
|
@@ -89,6 +89,11 @@
|
|
89
89
|
</zeroOrMore>
|
90
90
|
</element>
|
91
91
|
</element>
|
92
|
+
<element name="report" rngui:header="Reporting Annotation" rngui:fold="closed">
|
93
|
+
<element name="url" rngui:label='HTML Snippet'>
|
94
|
+
<data type="string" rngui:label="url to report snippet"/>
|
95
|
+
</element>
|
96
|
+
</element>
|
92
97
|
</element>
|
93
98
|
<element name="code" rngui:header="Implementation">
|
94
99
|
<element name="prepare" rngui:header="Prepare" rngui:label="Code" rngui:fold="closed_conditional">
|
@@ -137,4 +142,4 @@
|
|
137
142
|
</element>
|
138
143
|
</element>
|
139
144
|
</element>
|
140
|
-
</element>
|
145
|
+
</element>
|
data/cockpit/track.html
CHANGED
@@ -62,12 +62,41 @@
|
|
62
62
|
<div class='hidden' id='relaxngworker'></div>
|
63
63
|
<div id="trackfull">
|
64
64
|
<div id='graphcolumn'>
|
65
|
-
<div id="
|
66
|
-
<
|
67
|
-
<span
|
65
|
+
<div id="trackusage">
|
66
|
+
<div id='tracktitle'>
|
67
|
+
<span>
|
68
|
+
<a class="x-ui-button" name="glob_reload" title='reload' href=''>
|
69
|
+
<svg viewBox="0 -1.5 7 12" width="10" height="16">
|
70
|
+
<path
|
71
|
+
style="fill:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000000"
|
72
|
+
d="M 3.5,1.5 C 1.431441,1.5001975 -0.24540803,3.1770466 -0.24560554,5.2456055 -0.2454082,7.3141647 1.4314408,8.991014 3.5,8.9912113 5.5685591,8.991014 7.2454081,7.3141647 7.2456054,5.2456055 7.2454079,3.1770466 5.5685589,1.5001975 3.5,1.5 Z M 3.437195,4.0616198 c 0.020931,-5.551e-4 0.041873,-5.551e-4 0.062805,0 0.6537674,3.133e-4 1.1836723,0.5302183 1.1839856,1.1839857 C 4.6836723,5.8993729 4.1537674,6.4292778 3.5,6.4295912 2.8462325,6.4292778 2.3163276,5.8993729 2.3160142,5.2456055 2.315414,4.6155841 2.8080758,4.0953252 3.437195,4.0616198 Z"/>
|
73
|
+
</svg>
|
74
|
+
</a>
|
75
|
+
<a class="x-ui-button" name="glob_edit" title='edit' target='_blank' href='' id='current-monitor'><svg viewBox="0 -1.5 7 12" width="10" height="16">
|
76
|
+
<path
|
77
|
+
style="fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
78
|
+
d="M -0.25,7.8194404 0.57057194,10.599984 3.1882886,9.3540573 Z"/>
|
79
|
+
<path
|
80
|
+
style="fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
81
|
+
d="M 3.5215262,8.6074434 6.0527848,2.9361926 2.6144961,1.4015756 0.08323736,7.0728263 Z"/>
|
82
|
+
<path
|
83
|
+
style="fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
84
|
+
d="M 6.4439758,2.0597335 6.9719316,0.87685566 3.533643,-0.6577613 3.005687,0.52511656 Z"/>
|
85
|
+
</svg></a>
|
86
|
+
<a class="x-ui-button" name="glob_unshow" title='unshow'>
|
87
|
+
<svg viewBox="0 -1.5 7 12" width="10" height="16">
|
88
|
+
<path
|
89
|
+
style="fill:#000000;stroke-width:0;stop-color:#000000"
|
90
|
+
d="M 5.75,1.4999999 3.5,3.75 1.25,1.4999999 -0.25000013,3 2,5.25 -0.25000013,7.5 1.25,9.0000002 3.5,6.75 5.75,9.0000002 7.2500001,7.5 5,5.25 7.2500001,3 Z"/>
|
91
|
+
</svg>
|
92
|
+
</a>
|
93
|
+
</span>
|
94
|
+
<span> - </span>
|
95
|
+
<span id="title">Loading ...</span>
|
96
|
+
</div>
|
97
|
+
<div id='state'>
|
68
98
|
<span id="state_any">
|
69
|
-
<
|
70
|
-
<button name="state_start" title='start'>
|
99
|
+
<button name="state_start" title='start' style='display:none'>
|
71
100
|
<svg viewBox="0 -1.5 7 12" width="10" height="16">
|
72
101
|
<path
|
73
102
|
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
@@ -82,7 +111,6 @@
|
|
82
111
|
</svg>
|
83
112
|
</button>
|
84
113
|
<span id="state_extended">
|
85
|
-
<span> / </span>
|
86
114
|
<button name="state_replay" title='replay'>
|
87
115
|
<svg viewBox="0 -1.5 7 12" width="10" height="16">
|
88
116
|
<path
|
@@ -90,7 +118,6 @@
|
|
90
118
|
d="m -0.24999978,8.9999993 c 0,-2.7488167 0,-5.4976332 0,-8.24644997 C 1.1183278,0.76955385 2.4884861,0.71666052 3.8555376,0.79065567 4.5083287,0.83810218 5.2238942,1.0790874 5.5755039,1.7307256 6.1661398,2.7080902 6.0299484,4.2180754 5.1108772,4.9019222 4.7622397,5.1617467 4.3480204,5.2956156 3.9336064,5.3605366 4.9287868,5.9394132 5.4254071,7.0996814 6.0167729,8.0858876 6.1549588,8.3769029 6.4657247,8.7723933 6.5,8.9999999 c -0.5944185,0 -1.1888371,0 -1.7832559,0 C 4.0758679,7.9893475 3.4946311,6.9294648 2.7923497,5.9678488 2.4230355,5.5319748 1.8508715,5.5458842 1.3513114,5.5576027 c -0.1507526,-0.00412 -0.044576,0.272902 -0.076255,0.3990664 0,1.0144436 0,2.028887 0,3.0433307 -0.50835205,-3e-7 -1.01670555,8e-7 -1.52505618,-5e-7 z M 1.2750578,4.2411336 C 2.111059,4.2189781 2.9581852,4.3060525 3.7849326,4.1387394 4.4863715,3.8915585 4.5732952,2.6432813 3.9026802,2.2941453 3.5098807,2.068434 3.050719,2.1857044 2.6267379,2.1489138 c -0.4505578,-0.00242 -0.90112,0.00147 -1.3516801,-3.456e-4 0,0.6975176 0,1.3950347 0,2.0925522 z"
|
91
119
|
</svg>
|
92
120
|
</button>
|
93
|
-
<span> / </span>
|
94
121
|
<button name="state_abandon" title='abandon'>
|
95
122
|
<svg viewBox="0 -1.5 7 12" width="10" height="16">
|
96
123
|
<path
|
@@ -99,8 +126,10 @@
|
|
99
126
|
</svg>
|
100
127
|
</button>
|
101
128
|
</span>
|
129
|
+
<span> - Status: </span>
|
102
130
|
</span>
|
103
|
-
|
131
|
+
<span id="state_text">loading ...</span>
|
132
|
+
</div>
|
104
133
|
</div>
|
105
134
|
<div id='graphgrid'>
|
106
135
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:x="http://www.w3.org/1999/xlink" id='graphcanvas' width='1' height='1'></svg>
|
data/cpee.gemspec
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "cpee"
|
3
|
-
s.version = "2.0.
|
3
|
+
s.version = "2.0.13"
|
4
4
|
s.platform = Gem::Platform::RUBY
|
5
5
|
s.license = "LGPL-3.0"
|
6
6
|
s.summary = "Preliminary release of cloud process execution engine (cpee.org). If you just need workflow execution, without a rest service exposing it, then use WEEL."
|
7
7
|
|
8
8
|
s.description = "see http://cpee.org"
|
9
9
|
|
10
|
-
s.files = Dir['{example/**/*,server/**/*,tools/**/*,lib/**/*,cockpit/**/*,cockpit/themes/*/*/*,contrib/logo*,contrib/Screen*}'] - Dir['{server/instances/**/*,cockpit/js_libs/**/*}'] + %w(COPYING FEATURES.md INSTALL.md Rakefile cpee.gemspec README.md AUTHORS)
|
10
|
+
s.files = Dir['{example/**/*,server/**/*,tools/**/*,tools/archive,lib/**/*,cockpit/**/*,cockpit/themes/*/*/*,contrib/logo*,contrib/Screen*}'] - Dir['{server/instances/**/*,cockpit/js_libs/**/*}'] + %w(COPYING FEATURES.md INSTALL.md Rakefile cpee.gemspec README.md AUTHORS)
|
11
11
|
s.require_path = 'lib'
|
12
12
|
s.extra_rdoc_files = ['README.md']
|
13
13
|
s.bindir = 'tools'
|
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.email = 'juergen.mangler@gmail.com'
|
22
22
|
s.homepage = 'http://cpee.org/'
|
23
23
|
|
24
|
-
s.add_runtime_dependency 'riddl', '~> 0.
|
24
|
+
s.add_runtime_dependency 'riddl', '~> 0.108'
|
25
25
|
s.add_runtime_dependency 'weel', '~> 1.99', '>= 1.99.90'
|
26
26
|
s.add_runtime_dependency 'highline', '~> 2.0'
|
27
27
|
s.add_runtime_dependency 'json', '~>2.1'
|
data/lib/cpee/implementation.rb
CHANGED
@@ -72,7 +72,9 @@ module CPEE
|
|
72
72
|
opts[:infinite_loop_stop] ||= 10000
|
73
73
|
opts[:redis_path] ||= '/tmp/redis.sock'
|
74
74
|
opts[:redis_db] ||= 3
|
75
|
+
opts[:sse_keepalive_frequency] ||= 10
|
75
76
|
|
77
|
+
opts[:sse_connections] = {}
|
76
78
|
opts[:redis] = Redis.new(path: opts[:redis_path], db: opts[:redis_db])
|
77
79
|
opts[:statemachine] = CPEE::StateMachine.new opts[:states], %w{running simulating replaying finishing stopping abandoned finished} do |id|
|
78
80
|
opts[:redis].get("instance:#{id}/state")
|
@@ -88,13 +90,20 @@ module CPEE
|
|
88
90
|
|
89
91
|
Proc.new do
|
90
92
|
parallel do
|
91
|
-
CPEE::watch_services(
|
92
|
-
EM.add_periodic_timer(
|
93
|
-
CPEE::watch_services(
|
93
|
+
CPEE::watch_services(opts[:watchdog_start_off])
|
94
|
+
EM.add_periodic_timer(opts[:watchdog_frequency]) do ### start services
|
95
|
+
CPEE::watch_services(opts[:watchdog_start_off])
|
96
|
+
end
|
97
|
+
EM.defer do ### catch all sse connections
|
98
|
+
CPEE::Notifications::sse_distributor(opts)
|
99
|
+
end
|
100
|
+
EM.add_periodic_timer(opts[:sse_keepalive_frequency]) do
|
101
|
+
CPEE::Notifications::sse_heartbeat(opts)
|
94
102
|
end
|
95
103
|
end
|
104
|
+
|
96
105
|
cleanup do
|
97
|
-
CPEE::cleanup_services(
|
106
|
+
CPEE::cleanup_services(opts[:watchdog_start_off])
|
98
107
|
end
|
99
108
|
|
100
109
|
interface 'main' do
|
@@ -183,7 +192,7 @@ module CPEE
|
|
183
192
|
doc = XML::Smart::open_unprotected(opts[:properties_init])
|
184
193
|
doc.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
|
185
194
|
name = @p[0].value
|
186
|
-
id = redis.
|
195
|
+
id = redis.zrevrange('instances', 0, 0).first.to_i + 1
|
187
196
|
uuid = SecureRandom.uuid
|
188
197
|
instance = 'instance:' + id.to_s
|
189
198
|
redis.multi do |multi|
|
@@ -218,7 +227,7 @@ module CPEE
|
|
218
227
|
end
|
219
228
|
end rescue nil # all the ones that are not ok, are ignored
|
220
229
|
end
|
221
|
-
multi.set(File.join(instance, 'attributes', 'uuid'),
|
230
|
+
multi.set(File.join(instance, 'attributes', 'uuid'), uuid)
|
222
231
|
multi.zadd(File.join(instance, 'attributes'), -2, 'uuid')
|
223
232
|
multi.set(File.join(instance, 'attributes', 'info'), name)
|
224
233
|
multi.zadd(File.join(instance, 'attributes'), -1, 'info')
|
@@ -73,35 +73,40 @@ module CPEE
|
|
73
73
|
id = @a[0]
|
74
74
|
opts = @a[1]
|
75
75
|
key = @r[-1]
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
76
|
+
if CPEE::Persistence::exists_handler?(id,opts,key)
|
77
|
+
Riddl::Parameter::Complex.new("subscriptions","text/xml") do
|
78
|
+
ret = XML::Smart::string <<-END
|
79
|
+
<subscription xmlns='http://riddl.org/ns/common-patterns/notifications-producer/2.0'/>
|
80
|
+
END
|
81
|
+
url = CPEE::Persistence::extract_item(id,opts,File.join('handler',key,'url'))
|
82
|
+
ret.root.attributes['url'] = url if url && !url.empty?
|
83
|
+
items = {}
|
84
|
+
CPEE::Persistence::extract_handler(id,opts,key).each do |h|
|
85
|
+
t, i, v = h.split('/')
|
86
|
+
items[t] ||= []
|
87
|
+
items[t] << [i,v]
|
88
|
+
end
|
89
|
+
items.each do |k,v|
|
90
|
+
ret.root.add('topic').tap do |n|
|
91
|
+
n.attributes['id'] = k
|
92
|
+
v.each do |e|
|
93
|
+
n.add *e
|
94
|
+
end
|
93
95
|
end
|
94
96
|
end
|
97
|
+
ret.to_s
|
95
98
|
end
|
96
|
-
|
97
|
-
|
99
|
+
else
|
100
|
+
@status = 404
|
101
|
+
end
|
98
102
|
end
|
99
103
|
end #}}}
|
100
104
|
|
101
|
-
|
105
|
+
class CreateSubscription < Riddl::Implementation #{{{
|
102
106
|
def response
|
103
107
|
id = @a[0]
|
104
108
|
opts = @a[1]
|
109
|
+
|
105
110
|
key = Digest::MD5.hexdigest(Kernel::rand().to_s)
|
106
111
|
|
107
112
|
url = @p[0].name == 'url' ? @p.shift.value : nil
|
@@ -124,15 +129,19 @@ module CPEE
|
|
124
129
|
opts = @a[1]
|
125
130
|
key = @r.last
|
126
131
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
132
|
+
if CPEE::Persistence::exists_handler?(id,opts,key)
|
133
|
+
url = @p[0].name == 'url' ? @p.shift.value : nil
|
134
|
+
values = []
|
135
|
+
while @p.length > 0
|
136
|
+
topic = @p.shift.value
|
137
|
+
base = @p.shift
|
138
|
+
type = base.name
|
139
|
+
values += base.value.split(',').map { |i| File.join(topic,type[0..-2],i) }
|
140
|
+
end
|
141
|
+
@header = CPEE::Persistence::set_handler(id,opts,key,url,values,true)
|
142
|
+
else
|
143
|
+
@status = 404
|
134
144
|
end
|
135
|
-
@header = CPEE::Persistence::set_handler(id,opts,key,url,values,true)
|
136
145
|
end
|
137
146
|
end #}}}
|
138
147
|
|
@@ -146,41 +155,61 @@ module CPEE
|
|
146
155
|
opts = @a[1]
|
147
156
|
key = @r.last
|
148
157
|
|
149
|
-
|
158
|
+
if CPEE::Persistence::exists_handler?(id,opts,key)
|
159
|
+
DeleteSubscription::set(id,opts,key)
|
160
|
+
else
|
161
|
+
@status = 404
|
162
|
+
end
|
150
163
|
nil
|
151
164
|
end
|
152
165
|
end #}}}
|
153
166
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
+
def self::sse_distributor(opts) #{{{
|
168
|
+
conn = Redis.new(path: opts[:redis_path], db: opts[:redis_db])
|
169
|
+
conn.psubscribe('forward:*','event:state/change') do |on|
|
170
|
+
on.pmessage do |pat, what, message|
|
171
|
+
if pat == 'forward:*'
|
172
|
+
_, id, key = what.match(/forward(-end)?:([^\/]+)\/(.+)/).captures
|
173
|
+
opts.dig(:sse_connections,id.to_i,key)&.send message
|
174
|
+
elsif pat == 'event:state/change'
|
175
|
+
mess = JSON.parse(message[message.index(' ')+1..-1])
|
176
|
+
state = mess.dig('content','state')
|
177
|
+
if state == 'finished' || state == 'abandoned'
|
178
|
+
opts.dig(:sse_connections,mess.dig('instance').to_i)&.each do |key,sse|
|
179
|
+
EM.add_timer(10) do # just to be sure that all messages arrived. 10 seconds should be enough ... we think ... therefore we are (not sure)
|
180
|
+
sse.close
|
181
|
+
end
|
167
182
|
end
|
168
183
|
end
|
169
184
|
end
|
170
|
-
@conn.close
|
171
185
|
end
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
186
|
+
end
|
187
|
+
conn.close
|
188
|
+
end #}}}
|
189
|
+
def self::sse_heartbeat(opts) #{{{
|
190
|
+
opts.dig(:sse_connections).each do |id,keys|
|
191
|
+
keys.each do |key,sse|
|
192
|
+
sse.send_with_id('heartbeat', '42') unless sse&.closed?
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end #}}}
|
196
|
+
class SSE < Riddl::SSEImplementation #{{{
|
197
|
+
def onopen
|
198
|
+
@opts = @a[1]
|
199
|
+
@id = @a[0]
|
200
|
+
@key = @r[-2]
|
201
|
+
if CPEE::Persistence::exists_handler?(@id,@opts,@key)
|
202
|
+
@opts[:sse_connections][@id] ||= {}
|
203
|
+
@opts[:sse_connections][@id][@key] = self
|
204
|
+
true
|
205
|
+
else
|
206
|
+
false
|
177
207
|
end
|
178
208
|
end
|
179
209
|
|
180
210
|
def onclose
|
181
|
-
|
182
|
-
|
183
|
-
tredis.close
|
211
|
+
@opts.dig(:sse_connections,@id)&.delete(@key)
|
212
|
+
@opts.dig(:sse_connections)&.delete(@id) if @opts.dig(:sse_connections,@id)&.length == 0
|
184
213
|
DeleteSubscription::set(@id,@opts,@key)
|
185
214
|
end
|
186
215
|
end #}}}
|
@@ -660,8 +660,11 @@ module CPEE
|
|
660
660
|
@status = 422 # semantic error
|
661
661
|
else
|
662
662
|
begin
|
663
|
-
|
664
|
-
|
663
|
+
# force-encoding because johannes managed to sneak in ascii special characters. why the browser is not sanitizing it is beyond me.
|
664
|
+
PutDescription::set(id,opts,@p[0].value.read.force_encoding('UTF-8'))
|
665
|
+
rescue => e
|
666
|
+
puts e.message
|
667
|
+
puts e.backtrace
|
665
668
|
@status = 400
|
666
669
|
end
|
667
670
|
end
|
data/lib/cpee/persistence.rb
CHANGED
@@ -125,6 +125,9 @@ module CPEE
|
|
125
125
|
def self::extract_handler(id,opts,key) #{{{
|
126
126
|
opts[:redis].smembers("instance:#{id}/handlers/#{key}")
|
127
127
|
end #}}}
|
128
|
+
def self::exists_handler?(id,opts,key) #{{{
|
129
|
+
opts[:redis].exists?("instance:#{id}/handlers/#{key}")
|
130
|
+
end #}}}
|
128
131
|
def self::extract_handlers(id,opts) #{{{
|
129
132
|
opts[:redis].smembers("instance:#{id}/handlers").map do |e|
|
130
133
|
[e, opts[:redis].get("instance:#{id}/handlers/#{e}/url")]
|