cpee 2.0.16 → 2.0.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +4 -4
  2. data/cockpit/css/wfadaptor.css +17 -0
  3. data/cockpit/js/instance.js +3 -3
  4. data/cockpit/js_libs.zip +0 -0
  5. data/cockpit/themes/compact/rngs/closed_loop.rng +6 -3
  6. data/cockpit/themes/compact/rngs/closed_loop_control.rng +3 -0
  7. data/cockpit/themes/compact/rngs/closed_loop_measuring.rng +3 -0
  8. data/cockpit/themes/default/rngs/closed_loop.rng +6 -3
  9. data/cockpit/themes/default/rngs/closed_loop_control.rng +3 -0
  10. data/cockpit/themes/default/rngs/closed_loop_measuring.rng +3 -0
  11. data/cockpit/themes/diana/rngs/closed_loop.rng +6 -3
  12. data/cockpit/themes/diana/rngs/closed_loop_control.rng +3 -0
  13. data/cockpit/themes/diana/rngs/closed_loop_measuring.rng +3 -0
  14. data/cockpit/themes/extended/rngs/closed_loop.rng +6 -3
  15. data/cockpit/themes/extended/rngs/closed_loop_control.rng +3 -0
  16. data/cockpit/themes/extended/rngs/closed_loop_measuring.rng +3 -0
  17. data/cockpit/themes/model/rngs/call.rng +6 -1
  18. data/cockpit/themes/model/rngs/callmanipulate.rng +6 -1
  19. data/cockpit/themes/model/theme.js +1 -1
  20. data/cockpit/themes/packed/rngs/closed_loop.rng +6 -3
  21. data/cockpit/themes/packed/rngs/closed_loop_control.rng +3 -0
  22. data/cockpit/themes/packed/rngs/closed_loop_measuring.rng +3 -0
  23. data/cockpit/themes/preset/rngs/closed_loop.rng +6 -3
  24. data/cockpit/themes/preset/rngs/closed_loop_control.rng +3 -0
  25. data/cockpit/themes/preset/rngs/closed_loop_measuring.rng +3 -0
  26. data/cockpit/themes/preset/theme.js +1 -1
  27. data/cpee.gemspec +2 -2
  28. data/lib/cpee/controller.rb +6 -3
  29. data/lib/cpee/implementation.rb +23 -8
  30. data/lib/cpee/implementation_notifications.rb +1 -1
  31. data/lib/cpee/persistence.rb +2 -1
  32. data/lib/cpee/redis.rb +57 -0
  33. data/server/handlerwrappers/default.rb +16 -16
  34. data/server/routing/end.rb +16 -4
  35. data/server/routing/forward-events.rb +19 -7
  36. data/server/routing/forward-votes.rb +19 -7
  37. data/server/routing/persist.rb +27 -15
  38. data/tools/cpee +5 -5
  39. data/tools/server/{server.rb → cpee} +0 -0
  40. data/tools/test/README +4 -0
  41. data/tools/test/config.json +3 -0
  42. data/tools/test/contrib/graph_example.svg +1166 -0
  43. data/tools/test/contrib/legend.svg +817 -0
  44. data/tools/test/contrib/symbols.svg +224 -0
  45. data/tools/test/contrib/transformation1.xsl +264 -0
  46. data/tools/test/contrib/transformation2.xsl +10 -0
  47. data/tools/test/contrib/tree_example.svg +788 -0
  48. data/tools/test/css/model.css +24 -0
  49. data/tools/test/css/track.css +60 -0
  50. data/tools/test/css/ui.css +214 -0
  51. data/tools/test/css/wfadaptor.css +422 -0
  52. data/tools/test/edit.html +258 -0
  53. data/tools/test/graph.html +69 -0
  54. data/tools/test/index.html +258 -0
  55. data/tools/test/js/details.js +109 -0
  56. data/tools/test/js/instance.js +1344 -0
  57. data/tools/test/js/model.js +41 -0
  58. data/tools/test/js/parameters.js +82 -0
  59. data/tools/test/js/track.js +18 -0
  60. data/tools/test/js/ui.js +104 -0
  61. data/tools/test/js/wfadaptor.js +763 -0
  62. data/tools/test/js_libs.zip +0 -0
  63. data/tools/test/js_libs/Makefile +2 -0
  64. data/tools/test/js_libs/ansi_up.js +333 -0
  65. data/tools/test/js_libs/console.js +80 -0
  66. data/tools/test/js_libs/custommenu.css +84 -0
  67. data/tools/test/js_libs/custommenu.js +104 -0
  68. data/tools/test/js_libs/experiments1/relaxngui.css +185 -0
  69. data/tools/test/js_libs/experiments1/relaxngui.js +488 -0
  70. data/tools/test/js_libs/experiments1/rngtest9.html +60 -0
  71. data/tools/test/js_libs/experiments1/rngtest9.rng +35 -0
  72. data/tools/test/js_libs/experiments1/rngtest9.xml +8 -0
  73. data/tools/test/js_libs/jquery-2.2.4.min.js +4 -0
  74. data/tools/test/js_libs/jquery-3.2.1.min.js +4 -0
  75. data/tools/test/js_libs/jquery-3.3.1.min.js +2 -0
  76. data/tools/test/js_libs/jquery.browser.js +40 -0
  77. data/tools/test/js_libs/jquery.caret.min.js +10 -0
  78. data/tools/test/js_libs/jquery.cookie.js +117 -0
  79. data/tools/test/js_libs/jquery.min.js +1 -0
  80. data/tools/test/js_libs/jquery.svg.min.js +6 -0
  81. data/tools/test/js_libs/jquery.svgdom.min.js +6 -0
  82. data/tools/test/js_libs/markdown.min.js +1 -0
  83. data/tools/test/js_libs/parsequery.js +21 -0
  84. data/tools/test/js_libs/printf.js +368 -0
  85. data/tools/test/js_libs/relaxngui.css +213 -0
  86. data/tools/test/js_libs/relaxngui.js +543 -0
  87. data/tools/test/js_libs/strftime.min.js +1 -0
  88. data/tools/test/js_libs/tests/dataelements.html +59 -0
  89. data/tools/test/js_libs/tests/dataelements.rng +8 -0
  90. data/tools/test/js_libs/tests/dataelements.xml +3 -0
  91. data/tools/test/js_libs/tests/relaxngui.css +203 -0
  92. data/tools/test/js_libs/tests/relaxngui.js +502 -0
  93. data/tools/test/js_libs/tests/rngtest1.html +66 -0
  94. data/tools/test/js_libs/tests/rngtest1.rng +147 -0
  95. data/tools/test/js_libs/tests/rngtest1.xml +13 -0
  96. data/tools/test/js_libs/tests/rngtest2.html +60 -0
  97. data/tools/test/js_libs/tests/rngtest2.rng +6 -0
  98. data/tools/test/js_libs/tests/rngtest2.xml +3 -0
  99. data/tools/test/js_libs/tests/rngtest3.html +60 -0
  100. data/tools/test/js_libs/tests/rngtest3.rng +23 -0
  101. data/tools/test/js_libs/tests/rngtest3.xml +9 -0
  102. data/tools/test/js_libs/tests/rngtest4.html +60 -0
  103. data/tools/test/js_libs/tests/rngtest4.rng +19 -0
  104. data/tools/test/js_libs/tests/rngtest4.xml +12 -0
  105. data/tools/test/js_libs/tests/rngtest5.html +60 -0
  106. data/tools/test/js_libs/tests/rngtest5.rng +75 -0
  107. data/tools/test/js_libs/tests/rngtest5.xml +40 -0
  108. data/tools/test/js_libs/tests/rngtest6.html +60 -0
  109. data/tools/test/js_libs/tests/rngtest6.rng +24 -0
  110. data/tools/test/js_libs/tests/rngtest6.xml +6 -0
  111. data/tools/test/js_libs/tests/rngtest8.html +60 -0
  112. data/tools/test/js_libs/tests/rngtest8.rng +13 -0
  113. data/tools/test/js_libs/tests/rngtest8.xml +2 -0
  114. data/tools/test/js_libs/tests/rngtest9.html +60 -0
  115. data/tools/test/js_libs/tests/rngtest9.rng +31 -0
  116. data/tools/test/js_libs/tests/rngtest9.xml +8 -0
  117. data/tools/test/js_libs/ui.css +333 -0
  118. data/tools/test/js_libs/ui.html +168 -0
  119. data/tools/test/js_libs/ui.js +177 -0
  120. data/tools/test/js_libs/underscore.min.js +27 -0
  121. data/tools/test/js_libs/util.js +81 -0
  122. data/tools/test/js_libs/vkbeautify.0.99.00.beta.js +358 -0
  123. data/tools/test/js_libs/vkbeautify.js +1 -0
  124. data/tools/test/js_libs/webcomponents.min.js +196 -0
  125. data/tools/test/model.html +192 -0
  126. data/tools/test/rngs/attributes.rng +8 -0
  127. data/tools/test/rngs/dataelements.rng +8 -0
  128. data/tools/test/rngs/endpoints.rng +8 -0
  129. data/tools/test/templates.legacy/Async.xml +46 -0
  130. data/tools/test/templates.legacy/BCO.xml +70 -0
  131. data/tools/test/templates.legacy/BCS.xml +70 -0
  132. data/tools/test/templates.legacy/Centurio.xml +75 -0
  133. data/tools/test/templates.legacy/Concurrent.xml +40 -0
  134. data/tools/test/templates.legacy/Coopis Testset.xml +76 -0
  135. data/tools/test/templates.legacy/Endpoints and Data Manipulation.xml +30 -0
  136. data/tools/test/templates.legacy/ICSOC Testset.xml +95 -0
  137. data/tools/test/templates.legacy/Infinity.xml +28 -0
  138. data/tools/test/templates.legacy/Lego Boxer.xml +31 -0
  139. data/tools/test/templates.legacy/Lego Conveyor.xml +31 -0
  140. data/tools/test/templates.legacy/Lego Crane.xml +87 -0
  141. data/tools/test/templates.legacy/Lego Ejector.xml +55 -0
  142. data/tools/test/templates.legacy/Lego Full.xml +142 -0
  143. data/tools/test/templates.legacy/Lego Liddy.xml +40 -0
  144. data/tools/test/templates.legacy/Lego Plate.xml +31 -0
  145. data/tools/test/templates.legacy/Lego Transporter.xml +43 -0
  146. data/tools/test/templates.legacy/Lego_Part_1.xml +85 -0
  147. data/tools/test/templates.legacy/LgLinear.xml +65 -0
  148. data/tools/test/templates.legacy/Linear.xml +77 -0
  149. data/tools/test/templates.legacy/Log.xml +117 -0
  150. data/tools/test/templates.legacy/Mangler 1.xml +87 -0
  151. data/tools/test/templates.legacy/Mangler 2.xml +103 -0
  152. data/tools/test/templates.legacy/Manuel Labels.xml +55 -0
  153. data/tools/test/templates.legacy/Promise.xml +275 -0
  154. data/tools/test/templates.legacy/SOPROMO Test Sonification.xml +83 -0
  155. data/tools/test/templates.legacy/Subprocess.xml +56 -0
  156. data/tools/test/templates.legacy/Syncing P34 1.xml +77 -0
  157. data/tools/test/templates.legacy/Syncing P34 2.xml +77 -0
  158. data/tools/test/templates.legacy/Syncing P34 3.xml +77 -0
  159. data/tools/test/templates.legacy/Syncing P34.xml +77 -0
  160. data/tools/test/templates.legacy/TEST - Bad Loop.xml +173 -0
  161. data/tools/test/templates.legacy/TEST - Wrong Positions.xml +174 -0
  162. data/tools/test/templates.legacy/Take_5.xml +48 -0
  163. data/tools/test/templates.legacy/Update.xml +32 -0
  164. data/tools/test/templates.legacy/Worklist Parallel.xml +104 -0
  165. data/tools/test/templates.legacy/Worklist Test CPEE.xml +40 -0
  166. data/tools/test/templates.legacy/Worklist Test.xml +42 -0
  167. data/tools/test/templates.legacy/Worklist Test2.xml +43 -0
  168. data/tools/test/templates.legacy/convert_cpee2.rb +15 -0
  169. data/tools/test/templates.legacy/convert_preset.rb +32 -0
  170. data/tools/test/templates.legacy/testsets.xml +37 -0
  171. data/tools/test/templates.legacy/transformations.xml +4 -0
  172. data/tools/test/templates/Coopis 2010.xml +76 -0
  173. data/tools/test/templates/IUPC arXiv:1104.3609 P34 1.xml +77 -0
  174. data/tools/test/templates/IUPC arXiv:1104.3609 P34 2.xml +77 -0
  175. data/tools/test/templates/IUPC arXiv:1104.3609 P34 3.xml +77 -0
  176. data/tools/test/templates/Track Test Local.xml +82 -0
  177. data/tools/test/templates/Track Test.xml +82 -0
  178. data/tools/test/templates/UR-VUE 2020 Manual Adjust.xml +182 -0
  179. data/tools/test/templates/UR-VUE 2020 Solution Baseline.xml +203 -0
  180. data/tools/test/templates/UR-VUE 2020 Solution NN.xml +197 -0
  181. data/tools/test/templates/UR-VUE 2020 Solution View.xml +151 -0
  182. data/tools/test/templates/UR-VUE 2020.xml +26 -0
  183. data/tools/test/templates/Worklist.xml +42 -0
  184. data/tools/test/templates/instantiate.local/Take_Sub.xml +59 -0
  185. data/tools/test/templates/instantiate/Take_Perf.xml +46 -0
  186. data/tools/test/templates/instantiate/Take_Sub.xml +58 -0
  187. data/tools/test/templates/instantiate/Take_X.xml +48 -0
  188. data/tools/test/themes/compact/theme.js +1285 -0
  189. data/tools/test/themes/diana/theme.js +1650 -0
  190. data/tools/test/themes/extended/theme.js +1325 -0
  191. data/tools/test/themes/model/rngs/alternative.rng +1 -0
  192. data/tools/test/themes/model/rngs/call.rng +67 -0
  193. data/tools/test/themes/model/rngs/callmanipulate.rng +72 -0
  194. data/tools/test/themes/model/rngs/choose.rng +1 -0
  195. data/tools/test/themes/model/rngs/critical.rng +1 -0
  196. data/tools/test/themes/model/rngs/escape.rng +1 -0
  197. data/tools/test/themes/model/rngs/group.rng +1 -0
  198. data/tools/test/themes/model/rngs/loop.rng +1 -0
  199. data/tools/test/themes/model/rngs/manipulate.rng +1 -0
  200. data/tools/test/themes/model/rngs/otherwise.rng +1 -0
  201. data/tools/test/themes/model/rngs/parallel.rng +1 -0
  202. data/tools/test/themes/model/rngs/parallel_branch.rng +1 -0
  203. data/tools/test/themes/model/rngs/scripts.rng +7 -0
  204. data/tools/test/themes/model/rngs/stop.rng +1 -0
  205. data/tools/test/themes/model/rngs/terminate.rng +1 -0
  206. data/tools/test/themes/model/theme.js +1268 -0
  207. data/tools/test/themes/packed/theme.js +1286 -0
  208. data/tools/test/themes/preset/rngs/alternative.rng +25 -0
  209. data/tools/test/themes/preset/rngs/call.rng +122 -0
  210. data/tools/test/themes/preset/rngs/callmanipulate.rng +145 -0
  211. data/tools/test/themes/preset/rngs/choose.rng +14 -0
  212. data/tools/test/themes/preset/rngs/closed_loop.rng +62 -0
  213. data/tools/test/themes/preset/rngs/closed_loop_cancel.rng +5 -0
  214. data/tools/test/themes/preset/rngs/closed_loop_control.rng +31 -0
  215. data/tools/test/themes/preset/rngs/closed_loop_measuring.rng +12 -0
  216. data/tools/test/themes/preset/rngs/critical.rng +5 -0
  217. data/tools/test/themes/preset/rngs/escape.rng +1 -0
  218. data/tools/test/themes/preset/rngs/group.rng +3 -0
  219. data/tools/test/themes/preset/rngs/loop.rng +22 -0
  220. data/tools/test/themes/preset/rngs/manipulate.rng +9 -0
  221. data/tools/test/themes/preset/rngs/otherwise.rng +22 -0
  222. data/tools/test/themes/preset/rngs/parallel.rng +21 -0
  223. data/tools/test/themes/preset/rngs/parallel_branch.rng +8 -0
  224. data/tools/test/themes/preset/rngs/scripts.rng +23 -0
  225. data/tools/test/themes/preset/rngs/stop.rng +5 -0
  226. data/tools/test/themes/preset/rngs/terminate.rng +1 -0
  227. data/tools/test/themes/preset/symbols/alternative.svg +5 -0
  228. data/tools/test/themes/preset/symbols/arrow.svg +3 -0
  229. data/tools/test/themes/preset/symbols/call.svg +6 -0
  230. data/tools/test/themes/preset/symbols/callmanipulate.svg +8 -0
  231. data/tools/test/themes/preset/symbols/choose.svg +5 -0
  232. data/tools/test/themes/preset/symbols/choose_exclusive.svg +5 -0
  233. data/tools/test/themes/preset/symbols/choose_inclusive.svg +4 -0
  234. data/tools/test/themes/preset/symbols/closed_loop.svg +5 -0
  235. data/tools/test/themes/preset/symbols/closed_loop_cancel.svg +5 -0
  236. data/tools/test/themes/preset/symbols/closed_loop_control.svg +5 -0
  237. data/tools/test/themes/preset/symbols/closed_loop_measuring.svg +6 -0
  238. data/tools/test/themes/preset/symbols/complex.svg +8 -0
  239. data/tools/test/themes/preset/symbols/critical.svg +4 -0
  240. data/tools/test/themes/preset/symbols/end.svg +3 -0
  241. data/tools/test/themes/preset/symbols/escape.svg +5 -0
  242. data/tools/test/themes/preset/symbols/event_end.svg +3 -0
  243. data/tools/test/themes/preset/symbols/loop.svg +5 -0
  244. data/tools/test/themes/preset/symbols/manipulate.svg +4 -0
  245. data/tools/test/themes/preset/symbols/otherwise.svg +5 -0
  246. data/tools/test/themes/preset/symbols/parallel.svg +5 -0
  247. data/tools/test/themes/preset/symbols/parallel_branch.svg +5 -0
  248. data/tools/test/themes/preset/symbols/parallel_branch_compact.svg +4 -0
  249. data/tools/test/themes/preset/symbols/parallel_branch_event.svg +14 -0
  250. data/tools/test/themes/preset/symbols/parallel_branch_normal.svg +5 -0
  251. data/tools/test/themes/preset/symbols/scripts.svg +4 -0
  252. data/tools/test/themes/preset/symbols/start.svg +3 -0
  253. data/tools/test/themes/preset/symbols/stop.svg +5 -0
  254. data/tools/test/themes/preset/symbols/terminate.svg +4 -0
  255. data/tools/test/themes/preset/theme.js +1287 -0
  256. data/tools/test/track.html +142 -0
  257. metadata +222 -3
@@ -16,6 +16,7 @@ require 'fileutils'
16
16
  require 'redis'
17
17
  require 'riddl/server'
18
18
  require 'riddl/client'
19
+ require_relative 'redis'
19
20
  require_relative 'message'
20
21
  require_relative 'persistence'
21
22
  require_relative 'statemachine'
@@ -70,12 +71,22 @@ module CPEE
70
71
  opts[:watchdog_start_off] ||= false
71
72
  opts[:backend_instance] ||= 'instance.rb'
72
73
  opts[:infinite_loop_stop] ||= 10000
73
- opts[:redis_path] ||= '/tmp/redis.sock'
74
- opts[:redis_db] ||= 3
75
- opts[:sse_keepalive_frequency] ||= 10
76
74
 
75
+ ### set redis_cmd to nil if you want to do global
76
+ ### at least redis_path or redis_url and redis_db have to be set if you do global
77
+ opts[:redis_path] ||= 'redis.sock' # use e.g. /tmp/redis.sock for global stuff. Look it up in your redis config
78
+ opts[:redis_db] ||= 0
79
+ ### optional redis stuff
80
+ opts[:redis_url] ||= nil
81
+ opts[:redis_cmd] ||= 'redis-server --port 0 --unixsocket #redis_path# --unixsocketperm 600 --pidfile #redis_pid# --dir #redis_db_dir# --dbfilename #redis_db_name# --databases 1 --save 900 1 --save 300 10 --save 60 10000 --rdbcompression yes --daemonize yes'
82
+ opts[:redis_pid] ||= 'redis.pid' # use e.g. /var/run/redis.pid if you do global. Look it up in your redis config
83
+ opts[:redis_db_name] ||= 'redis.rdb' # use e.g. /var/lib/redis.rdb for global stuff. Look it up in your redis config
84
+
85
+ CPEE::redis_connect opts
86
+
87
+ opts[:sse_keepalive_frequency] ||= 10
77
88
  opts[:sse_connections] = {}
78
- opts[:redis] = Redis.new(path: opts[:redis_path], db: opts[:redis_db])
89
+
79
90
  opts[:statemachine] = CPEE::StateMachine.new opts[:states], %w{running simulating replaying finishing stopping abandoned finished} do |id|
80
91
  opts[:redis].get("instance:#{id}/state")
81
92
  end
@@ -90,9 +101,9 @@ module CPEE
90
101
 
91
102
  Proc.new do
92
103
  parallel do
93
- CPEE::watch_services(opts[:watchdog_start_off])
104
+ CPEE::watch_services(opts[:watchdog_start_off],opts[:redis_url],File.join(opts[:basepath],opts[:redis_path]),opts[:redis_db])
94
105
  EM.add_periodic_timer(opts[:watchdog_frequency]) do ### start services
95
- CPEE::watch_services(opts[:watchdog_start_off])
106
+ CPEE::watch_services(opts[:watchdog_start_off],opts[:redis_url],File.join(opts[:basepath],opts[:redis_path]),opts[:redis_db])
96
107
  end
97
108
  EM.defer do ### catch all sse connections
98
109
  CPEE::Notifications::sse_distributor(opts)
@@ -132,14 +143,18 @@ module CPEE
132
143
  end
133
144
  end
134
145
 
135
- def self::watch_services(watchdog_start_off)
146
+ def self::watch_services(watchdog_start_off,url,path,db)
136
147
  return if watchdog_start_off
137
148
  EM.defer do
138
149
  Dir[File.join(__dir__,'..','..','server','routing','*.rb')].each do |s|
139
150
  s = s.sub(/\.rb$/,'')
140
151
  pid = (File.read(s + '.pid').to_i rescue nil)
141
152
  if (pid.nil? || !(Process.kill(0, pid) rescue false)) && !File.exist?(s + '.lock')
142
- system "#{s}.rb restart 1>/dev/null 2>&1"
153
+ if url.nil?
154
+ system "#{s}.rb -p \"#{path}\" -d #{db} restart 1>/dev/null 2>&1"
155
+ else
156
+ system "#{s}.rb -u \"#{url}\" -d #{db} restart 1>/dev/null 2>&1"
157
+ end
143
158
  puts "➡ Service #{File.basename(s,'.rb')} started ..."
144
159
  end
145
160
  end
@@ -165,7 +165,7 @@ module CPEE
165
165
  end #}}}
166
166
 
167
167
  def self::sse_distributor(opts) #{{{
168
- conn = Redis.new(path: opts[:redis_path], db: opts[:redis_db])
168
+ conn = opts[:redis_dyn].call
169
169
  conn.psubscribe('forward:*','event:state/change') do |on|
170
170
  on.pmessage do |pat, what, message|
171
171
  if pat == 'forward:*'
@@ -30,7 +30,8 @@ module CPEE
30
30
  YAML::dump({
31
31
  :host => opts[:host],
32
32
  :url => opts[:url],
33
- :redis_path => opts[:redis_path],
33
+ :redis_url => opts[:redis_url],
34
+ :redis_path => File.join(opts[:basepath],opts[:redis_path]),
34
35
  :redis_db => opts[:redis_db],
35
36
  :global_handlerwrappers => opts[:global_handlerwrappers],
36
37
  :handlerwrappers => opts[:handlerwrappers]
@@ -0,0 +1,57 @@
1
+ # This file is part of CPEE.
2
+ #
3
+ # CPEE is free software: you can redistribute it and/or modify it under the terms
4
+ # of the GNU General Public License as published by the Free Software Foundation,
5
+ # either version 3 of the License, or (at your option) any later version.
6
+ #
7
+ # CPEE is distributed in the hope that it will be useful, but WITHOUT ANY
8
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
9
+ # PARTICULAR PURPOSE. See the GNU General Public License for more details.
10
+ #
11
+ # You should have received a copy of the GNU General Public License along with
12
+ # CPEE (file COPYING in the main directory). If not, see
13
+ # <http://www.gnu.org/licenses/>.
14
+
15
+ require 'redis'
16
+
17
+ module CPEE
18
+ def self::redis_connect(opts)
19
+ if opts[:redis_cmd].nil?
20
+ begin
21
+ if opts[:redis_path]
22
+ opts[:redis_dyn] = Proc.new { Redis.new(path: opts[:redis_path], db: opts[:redis_db]) }
23
+ elsif opts[:redis_url]
24
+ opts[:redis_dyn] = Proc.new { Redis.new(url: opts[:redis_url], db: opts[:redis_db]) }
25
+ else
26
+ raise
27
+ end
28
+ opts[:redis] = opts[:redis_dyn].call
29
+ opts[:redis].dbsize
30
+ rescue
31
+ puts 'can not connect to redis. check if it is running and cpee is configured correctly ...'
32
+ exit
33
+ end
34
+ else # we always assume file socket if redis is startet locally
35
+ opts[:redis_dyn] = Proc.new { Redis.new(path: File.join(opts[:basepath],opts[:redis_path]), db: opts[:redis_db].to_i) }
36
+ begin
37
+ opts[:redis] = opts[:redis_dyn].call
38
+ opts[:redis].dbsize
39
+ rescue
40
+ rcmd = opts[:redis_cmd]
41
+ rcmd.gsub! /#redis_path#/, File.join(opts[:basepath],opts[:redis_path])
42
+ rcmd.gsub! /#redis_db_dir#/, opts[:basepath]
43
+ rcmd.gsub! /#redis_db_name#/, opts[:redis_db_name]
44
+ rcmd.gsub! /#redis_pid#/, File.join(opts[:basepath],opts[:redis_pid])
45
+ res = system rcmd
46
+ if res
47
+ puts 'starting redis ... it will keep running, just to let you know ...'
48
+ sleep 1
49
+ retry
50
+ else
51
+ puts 'can not start redis. check if cpee is configured correctly ...'
52
+ exit
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -109,7 +109,7 @@ class DefaultHandlerWrapper < WEEL::HandlerWrapperBase
109
109
 
110
110
  client = Riddl::Client.new(tendpoint)
111
111
 
112
- @controller.callback(self,callback,:activity_uuid => @handler_activity_uuid, :label => @label, :activity => @handler_position)
112
+ @controller.callback(self,callback,:'activity-uuid' => @handler_activity_uuid, :label => @label, :activity => @handler_position)
113
113
  @handler_passthrough = callback
114
114
 
115
115
  status, result, headers = client.request type => params
@@ -120,10 +120,10 @@ class DefaultHandlerWrapper < WEEL::HandlerWrapperBase
120
120
  callback([ Riddl::Parameter::Complex.new('error','application/json',StringIO.new(JSON::generate({ 'status' => status, 'error' => c }))) ], headers)
121
121
  else
122
122
  if headers['CPEE_INSTANTIATION']
123
- @controller.notify("task/instantiation", :activity_uuid => @handler_activity_uuid, :label => @label, :activity => @handler_position, :endpoint => @handler_endpoint, :received => CPEE::ValueHelper.parse(headers['CPEE_INSTANTIATION']))
123
+ @controller.notify("task/instantiation", :'activity-uuid' => @handler_activity_uuid, :label => @label, :activity => @handler_position, :endpoint => @handler_endpoint, :received => CPEE::ValueHelper.parse(headers['CPEE_INSTANTIATION']))
124
124
  end
125
125
  if headers['CPEE_EVENT']
126
- @controller.notify("task/#{headers['CPEE_EVENT'].gsub(/[^\w_-]/,'')}", :activity_uuid => @handler_activity_uuid, :label => @label, :activity => @handler_position, :endpoint => @handler_endpoint)
126
+ @controller.notify("task/#{headers['CPEE_EVENT'].gsub(/[^\w_-]/,'')}", :'activity-uuid' => @handler_activity_uuid, :label => @label, :activity => @handler_position, :endpoint => @handler_endpoint)
127
127
  end
128
128
  if headers['CPEE_CALLBACK'] && headers['CPEE_CALLBACK'] == 'true' && result.any?
129
129
  headers['CPEE_UPDATE'] = true
@@ -142,11 +142,11 @@ class DefaultHandlerWrapper < WEEL::HandlerWrapperBase
142
142
  @sensors = parameters.dig(:stream,:sensors)
143
143
  @aggregators = parameters.dig(:stream,:aggregators)
144
144
  @costs = parameters.dig(:stream,:costs)
145
- @controller.notify("activity/calling", :activity_uuid => @handler_activity_uuid, :label => @label, :activity => @handler_position, :passthrough => passthrough, :endpoint => @handler_endpoint, :parameters => parameters)
145
+ @controller.notify("activity/calling", :'activity-uuid' => @handler_activity_uuid, :label => @label, :activity => @handler_position, :passthrough => passthrough, :endpoint => @handler_endpoint, :parameters => parameters)
146
146
  if passthrough.to_s.empty?
147
147
  proto_curl parameters
148
148
  else
149
- @controller.callback(self,passthrough,:activity_uuid => @handler_activity_uuid, :label => @label, :activity => @handler_position)
149
+ @controller.callback(self,passthrough,:'activity-uuid' => @handler_activity_uuid, :label => @label, :activity => @handler_position)
150
150
  @handler_passthrough = passthrough
151
151
  end
152
152
  end # }}}
@@ -175,33 +175,33 @@ class DefaultHandlerWrapper < WEEL::HandlerWrapperBase
175
175
  end # }}}
176
176
 
177
177
  def inform_activity_done # {{{
178
- @controller.notify("activity/done", :activity_uuid => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position)
178
+ @controller.notify("activity/done", :'activity-uuid' => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position)
179
179
  end # }}}
180
180
  def inform_activity_manipulate # {{{
181
- @controller.notify("activity/manipulating", :activity_uuid => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position)
181
+ @controller.notify("activity/manipulating", :'activity-uuid' => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position)
182
182
  end # }}}
183
183
  def inform_activity_failed(err) # {{{
184
184
  puts err.message
185
185
  puts err.backtrace
186
- @controller.notify("activity/failed", :activity_uuid => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position, :message => err.message, :line => err.backtrace[0].match(/(.*?):(\d+):/)[2], :where => err.backtrace[0].match(/(.*?):(\d+):/)[1])
186
+ @controller.notify("activity/failed", :'activity-uuid' => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position, :message => err.message, :line => err.backtrace[0].match(/(.*?):(\d+):/)[2], :where => err.backtrace[0].match(/(.*?):(\d+):/)[1])
187
187
  end # }}}
188
188
  def inform_manipulate_change(status,changed_dataelements,changed_endpoints,dataelements,endpoints) # {{{
189
189
  unless status.nil?
190
- @controller.notify("status/change", :activity_uuid => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position, :id => status.id, :message => status.message)
190
+ @controller.notify("status/change", :'activity-uuid' => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position, :id => status.id, :message => status.message)
191
191
  end
192
192
  unless changed_dataelements.nil?
193
- @controller.notify("dataelements/change", :activity_uuid => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position, :changed => changed_dataelements, :values => dataelements)
193
+ @controller.notify("dataelements/change", :'activity-uuid' => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position, :changed => changed_dataelements, :values => dataelements)
194
194
  end
195
195
  unless changed_endpoints.nil?
196
- @controller.notify("endpoints/change", :activity_uuid => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position, :changed => changed_endpoints, :values => endpoints)
196
+ @controller.notify("endpoints/change", :'activity-uuid' => @handler_activity_uuid, :endpoint => @handler_endpoint, :label => @label, :activity => @handler_position, :changed => changed_endpoints, :values => endpoints)
197
197
  end
198
198
  end # }}}
199
199
 
200
200
  def vote_sync_after # {{{
201
- @controller.vote("activity/syncing_after", :activity_uuid => @handler_activity_uuid, :endpoint => @handler_endpoint, :activity => @handler_position, :label => @label)
201
+ @controller.vote("activity/syncing_after", :'activity-uuid' => @handler_activity_uuid, :endpoint => @handler_endpoint, :activity => @handler_position, :label => @label)
202
202
  end # }}}
203
203
  def vote_sync_before(parameters=nil) # {{{
204
- @controller.vote("activity/syncing_before", :activity_uuid => @handler_activity_uuid, :endpoint => @handler_endpoint, :activity => @handler_position, :label => @label, :parameters => parameters)
204
+ @controller.vote("activity/syncing_before", :'activity-uuid' => @handler_activity_uuid, :endpoint => @handler_endpoint, :activity => @handler_position, :label => @label, :parameters => parameters)
205
205
  end # }}}
206
206
 
207
207
  def simplify_result(result)
@@ -260,13 +260,13 @@ class DefaultHandlerWrapper < WEEL::HandlerWrapperBase
260
260
  end
261
261
 
262
262
  def callback(result=nil,options={})
263
- @controller.notify("activity/receiving", :activity_uuid => @handler_activity_uuid, :label => @label, :activity => @handler_position, :endpoint => @handler_endpoint, :received => structurize_result(result), :sensors => @sensors, :aggregators => @aggregators, :costs => @costs)
263
+ @controller.notify("activity/receiving", :'activity-uuid' => @handler_activity_uuid, :label => @label, :activity => @handler_position, :endpoint => @handler_endpoint, :received => structurize_result(result), :sensors => @sensors, :aggregators => @aggregators, :costs => @costs)
264
264
  result = simplify_result(result)
265
265
  @handler_returnValue = result
266
266
  @handler_returnOptions = options
267
267
  if options['CPEE_UPDATE']
268
268
  if options['CPEE_UPDATE_STATUS']
269
- @controller.notify("activity/status", :activity_uuid => @handler_activity_uuid, :label => @label, :activity => @handler_position, :endpoint => @handler_endpoint, :status => options['CPEE_UPDATE_STATUS'])
269
+ @controller.notify("activity/status", :'activity-uuid' => @handler_activity_uuid, :label => @label, :activity => @handler_position, :endpoint => @handler_endpoint, :status => options['CPEE_UPDATE_STATUS'])
270
270
  end
271
271
  @handler_continue.continue WEEL::Signal::Again
272
272
  else
@@ -290,7 +290,7 @@ class DefaultHandlerWrapper < WEEL::HandlerWrapperBase
290
290
  pp "#{type} - #{nesting} - #{tid} - #{parent} - #{parameters.inspect}"
291
291
 
292
292
  @controller.vote("simulating/step",
293
- :activity_uuid => @handler_activity_uuid,
293
+ :'activity-uuid' => @handler_activity_uuid,
294
294
  :label => @label,
295
295
  :activity => tid,
296
296
  :endpoint => @handler_endpoint,
@@ -17,18 +17,30 @@
17
17
  require 'json'
18
18
  require 'redis'
19
19
  require 'daemonite'
20
+ require_relative '../../lib/cpee/redis'
20
21
 
21
22
  Daemonite.new do |opts|
22
- redis = Redis.new(path: "/tmp/redis.sock", db: 3)
23
- pubsubredis = Redis.new(path: "/tmp/redis.sock", db: 3)
23
+ opts[:runtime_opts] += [
24
+ ["--url=URL", "-uURL", "Specify redis url", ->(p){ opts[:redis_url] = p }],
25
+ ["--path=PATH", "-pPATH", "Specify redis path, e.g. /tmp/redis.sock", ->(p){ opts[:redis_path] = p }],
26
+ ["--db=DB", "-dDB", "Specify redis db, e.g. 1", ->(p) { opts[:redis_db] = p.to_i }]
27
+ ]
28
+
29
+ on startup do
30
+ opts[:redis_path] ||= '/tmp/redis.sock'
31
+ opts[:redis_db] ||= 1
32
+
33
+ CPEE::redis_connect opts
34
+ opts[:pubsubredis] = opts[:redis_dyn].call
35
+ end
24
36
 
25
37
  run do
26
- pubsubredis.psubscribe('callback-end:*') do |on|
38
+ opts[:pubsubredis].psubscribe('callback-end:*') do |on|
27
39
  on.pmessage do |pat, what, message|
28
40
  _, key = what.split(':')
29
41
  index = message.index(' ')
30
42
  instance = message[0...index]
31
- redis.multi do |multi|
43
+ opts[:redis].multi do |multi|
32
44
  multi.srem("instance:#{instance}/callbacks",key)
33
45
  multi.del("instance:#{instance}/callback/#{key}/uuid")
34
46
  multi.del("instance:#{instance}/callback/#{key}/label")
@@ -17,13 +17,25 @@
17
17
  require 'redis'
18
18
  require 'daemonite'
19
19
  require 'riddl/client'
20
+ require_relative '../../lib/cpee/redis'
20
21
 
21
22
  Daemonite.new do |opts|
22
- redis = Redis.new(path: "/tmp/redis.sock", db: 3)
23
- pubsubredis = Redis.new(path: "/tmp/redis.sock", db: 3)
23
+ opts[:runtime_opts] += [
24
+ ["--url=URL", "-uURL", "Specify redis url", ->(p){ opts[:redis_url] = p }],
25
+ ["--path=PATH", "-pPATH", "Specify redis path, e.g. /tmp/redis.sock", ->(p){ opts[:redis_path] = p }],
26
+ ["--db=DB", "-dDB", "Specify redis db, e.g. 1", ->(p) { opts[:redis_db] = p.to_i }]
27
+ ]
28
+
29
+ on startup do
30
+ opts[:redis_path] ||= '/tmp/redis.sock'
31
+ opts[:redis_db] ||= 1
32
+
33
+ CPEE::redis_connect opts
34
+ opts[:pubsubredis] = opts[:redis_dyn].call
35
+ end
24
36
 
25
37
  run do
26
- pubsubredis.psubscribe('event:*') do |on|
38
+ opts[:pubsubredis].psubscribe('event:*') do |on|
27
39
  on.pmessage do |pat, what, message|
28
40
  index = message.index(' ')
29
41
  mess = message[index+1..-1]
@@ -33,11 +45,11 @@ Daemonite.new do |opts|
33
45
  topic = ::File::dirname(event)
34
46
  name = ::File::basename(event)
35
47
  long = File.join(topic,type,name)
36
- redis.smembers("instance:#{instance}/handlers").each do |key|
37
- if redis.smembers("instance:#{instance}/handlers/#{key}").include? long
38
- url = redis.get("instance:#{instance}/handlers/#{key}/url")
48
+ opts[:redis].smembers("instance:#{instance}/handlers").each do |key|
49
+ if opts[:redis].smembers("instance:#{instance}/handlers/#{key}").include? long
50
+ url = opts[:redis].get("instance:#{instance}/handlers/#{key}/url")
39
51
  if url.nil? || url == ""
40
- redis.publish("forward:#{instance}/#{key}",mess)
52
+ opts[:redis].publish("forward:#{instance}/#{key}",mess)
41
53
  else
42
54
  p "#{type}/#{topic}/#{event}-#{url}"
43
55
  client = Riddl::Client.new(url)
@@ -19,6 +19,7 @@ require 'daemonite'
19
19
  require 'riddl/client'
20
20
  require 'json'
21
21
  require_relative '../../lib/cpee/message'
22
+ require_relative '../../lib/cpee/redis'
22
23
 
23
24
  def persist_handler(instance,key,mess,redis) #{{{
24
25
  redis.multi do |multi|
@@ -44,11 +45,22 @@ def send_response(instance,key,url,value,redis) #{{{
44
45
  end #}}}
45
46
 
46
47
  Daemonite.new do |opts|
47
- redis = Redis.new(path: "/tmp/redis.sock", db: 3)
48
- pubsubredis = Redis.new(path: "/tmp/redis.sock", db: 3)
48
+ opts[:runtime_opts] += [
49
+ ["--url=URL", "-uURL", "Specify redis url", ->(p){ opts[:redis_url] = p }],
50
+ ["--path=PATH", "-pPATH", "Specify redis path, e.g. /tmp/redis.sock", ->(p){ opts[:redis_path] = p }],
51
+ ["--db=DB", "-dDB", "Specify redis db, e.g. 1", ->(p) { opts[:redis_db] = p.to_i }]
52
+ ]
53
+
54
+ on startup do
55
+ opts[:redis_path] ||= '/tmp/redis.sock'
56
+ opts[:redis_db] ||= 1
57
+
58
+ CPEE::redis_connect opts
59
+ opts[:pubsubredis] = opts[:redis_dyn].call
60
+ end
49
61
 
50
62
  run do
51
- pubsubredis.psubscribe('vote:*') do |on|
63
+ opts[:pubsubredis].psubscribe('vote:*') do |on|
52
64
  on.pmessage do |pat, what, message|
53
65
  index = message.index(' ')
54
66
  mess = message[index+1..-1]
@@ -60,15 +72,15 @@ Daemonite.new do |opts|
60
72
  name = ::File::basename(event)
61
73
  long = File.join(topic,type,name)
62
74
 
63
- redis.smembers("instance:#{instance}/handlers").each do |subscription_key|
64
- if redis.smembers("instance:#{instance}/handlers/#{subscription_key}").include? long
75
+ opts[:redis].smembers("instance:#{instance}/handlers").each do |subscription_key|
76
+ if opts[:redis].smembers("instance:#{instance}/handlers/#{subscription_key}").include? long
65
77
  m = JSON.parse(mess)
66
78
  callback_key = m.dig('content','key')
67
- url = redis.get("instance:#{instance}/handlers/#{subscription_key}/url")
79
+ url = opts[:redis].get("instance:#{instance}/handlers/#{subscription_key}/url")
68
80
 
69
81
  if url.nil? || url == ""
70
82
  persist_handler instance, callback_key, m, redis
71
- redis.publish("forward:#{instance}/#{subscription_key}",mess)
83
+ opts[:redis].publish("forward:#{instance}/#{subscription_key}",mess)
72
84
  else
73
85
  client = Riddl::Client.new(url)
74
86
  callback = m['instance-url'] + '/callbacks/' + subscription_key
@@ -18,6 +18,7 @@ require 'json'
18
18
  require 'redis'
19
19
  require 'daemonite'
20
20
  require_relative '../../lib/cpee/value_helper'
21
+ require_relative '../../lib/cpee/redis'
21
22
 
22
23
  EVENTS = %w{
23
24
  event:state/change
@@ -34,18 +35,29 @@ EVENTS = %w{
34
35
  }
35
36
 
36
37
  Daemonite.new do |opts|
37
- redis = Redis.new(path: "/tmp/redis.sock", db: 3)
38
- pubsubredis = Redis.new(path: "/tmp/redis.sock", db: 3)
38
+ opts[:runtime_opts] += [
39
+ ["--url=URL", "-uURL", "Specify redis url", ->(p){ opts[:redis_url] = p }],
40
+ ["--path=PATH", "-pPATH", "Specify redis path, e.g. /tmp/redis.sock", ->(p){ opts[:redis_path] = p }],
41
+ ["--db=DB", "-dDB", "Specify redis db, e.g. 1", ->(p) { opts[:redis_db] = p.to_i }]
42
+ ]
43
+
44
+ on startup do
45
+ opts[:redis_path] ||= '/tmp/redis.sock'
46
+ opts[:redis_db] ||= 1
47
+
48
+ CPEE::redis_connect opts
49
+ opts[:pubsubredis] = opts[:redis_dyn].call
50
+ end
39
51
 
40
52
  run do
41
- pubsubredis.subscribe(EVENTS) do |on|
53
+ opts[:pubsubredis].subscribe(EVENTS) do |on|
42
54
  on.message do |what, message|
43
55
  mess = JSON.parse(message[message.index(' ')+1..-1])
44
56
  instance = mess.dig('instance')
45
57
  case what
46
58
  when 'callback:activity/content'
47
59
  key = mess.dig('content','key')
48
- redis.multi do |multi|
60
+ opts[:redis].multi do |multi|
49
61
  multi.sadd("instance:#{instance}/callbacks",key)
50
62
  multi.set("instance:#{instance}/callback/#{key}/uuid",mess.dig('content','activity_uuid'))
51
63
  multi.set("instance:#{instance}/callback/#{key}/label",mess.dig('content','label'))
@@ -53,21 +65,21 @@ Daemonite.new do |opts|
53
65
  multi.set("instance:#{instance}/callback/#{key}/type",'callback')
54
66
  end
55
67
  when 'event:state/change'
56
- redis.multi do |multi|
68
+ opts[:redis].multi do |multi|
57
69
  multi.set("instance:#{instance}/state",mess.dig('content','state'))
58
- multi.set("instance:#{instance}/state/@changed",mess.dig('content','timestamp'))
70
+ multi.set("instance:#{instance}/state/@changed",mess.dig('timestamp'))
59
71
  end
60
72
  when 'event:handlerwrapper/change'
61
- redis.set("instance:#{instance}/handlerwrapper",mess.dig('content','handlerwrapper'))
73
+ opts[:redis].set("instance:#{instance}/handlerwrapper",mess.dig('content','handlerwrapper'))
62
74
  when 'event:description/change'
63
- redis.multi do |multi|
75
+ opts[:redis].multi do |multi|
64
76
  multi.set("instance:#{instance}/description",mess.dig('content','description'))
65
77
  multi.set("instance:#{instance}/dslx",mess.dig('content','dslx'))
66
78
  multi.set("instance:#{instance}/dsl",mess.dig('content','dsl'))
67
79
  end
68
80
  when 'event:dataelements/change', 'event:endpoints/change', 'event:attributes/change'
69
81
  topic = mess.dig('topic')
70
- redis.multi do |multi|
82
+ opts[:redis].multi do |multi|
71
83
  mess.dig('content','changed')&.each_with_index do |c,i|
72
84
  unless what == 'event:attributes/change' && c == 'uuid'
73
85
  multi.zadd("instance:#{instance}/#{topic}",i,c)
@@ -86,7 +98,7 @@ Daemonite.new do |opts|
86
98
  end
87
99
  end
88
100
  when 'event:transformation/change'
89
- redis.multi do |multi|
101
+ opts[:redis].multi do |multi|
90
102
  multi.set("instance:#{instance}/transformation/description/",mess.dig('content','description'))
91
103
  multi.set("instance:#{instance}/transformation/description/@type",mess.dig('content','description_type'))
92
104
  multi.set("instance:#{instance}/transformation/dataelements/",mess.dig('content','dataelements'))
@@ -95,12 +107,12 @@ Daemonite.new do |opts|
95
107
  multi.set("instance:#{instance}/transformation/endpoints/@type",mess.dig('content','endpoints_type'))
96
108
  end
97
109
  when 'event:status/change'
98
- redis.multi do |multi|
110
+ opts[:redis].multi do |multi|
99
111
  multi.set("instance:#{instance}/status/id",mess.dig('content','id'))
100
112
  multi.set("instance:#{instance}/status/message",mess.dig('content','message'))
101
113
  end
102
114
  when 'event:position/change'
103
- redis.multi do |multi|
115
+ opts[:redis].multi do |multi|
104
116
  c = mess.dig('content')
105
117
  c.dig('unmark')&.each do |ele|
106
118
  multi.srem("instance:#{instance}/positions",ele['position'])
@@ -127,7 +139,7 @@ Daemonite.new do |opts|
127
139
  end
128
140
  end
129
141
  when 'event:handler/change'
130
- redis.multi do |multi|
142
+ opts[:redis].multi do |multi|
131
143
  mess.dig('content','changed').each do |c|
132
144
  multi.sadd("instance:#{instance}/handlers",mess.dig('content','key'))
133
145
  multi.sadd("instance:#{instance}/handlers/#{mess.dig('content','key')}",c)
@@ -139,8 +151,8 @@ Daemonite.new do |opts|
139
151
  multi.srem("instance:#{instance}/handlers/#{c}",mess.dig('content','key'))
140
152
  end
141
153
  end
142
- if redis.scard("instance:#{instance}/handlers/#{mess.dig('content','key')}") < 1
143
- redis.multi do |multi|
154
+ if opts[:redis].scard("instance:#{instance}/handlers/#{mess.dig('content','key')}") < 1
155
+ opts[:redis].multi do |multi|
144
156
  multi.del("instance:#{instance}/handlers/#{mess.dig('content','key')}/url")
145
157
  multi.srem("instance:#{instance}/handlers",mess.dig('content','key'))
146
158
  end