durable_rules 0.33.13 → 0.34.01
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/deps/hiredis/Makefile +110 -41
- data/deps/hiredis/async.c +87 -22
- data/deps/hiredis/async.h +4 -0
- data/deps/hiredis/fmacros.h +6 -1
- data/deps/hiredis/hiredis.c +270 -534
- data/deps/hiredis/hiredis.h +89 -76
- data/deps/hiredis/net.c +206 -47
- data/deps/hiredis/net.h +12 -6
- data/deps/hiredis/read.c +525 -0
- data/deps/hiredis/read.h +116 -0
- data/deps/hiredis/sds.c +260 -47
- data/deps/hiredis/sds.h +11 -6
- data/deps/hiredis/test.c +171 -18
- data/deps/hiredis/win32.h +42 -0
- data/librb/durable.rb +35 -6
- data/librb/engine.rb +173 -40
- data/src/rules/events.c +42 -4
- data/src/rules/net.c +184 -96
- data/src/rules/net.h +10 -0
- data/src/rules/rules.h +13 -0
- data/src/rulesrb/rules.c +55 -0
- metadata +5 -3
- data/deps/hiredis/zmalloc.h +0 -13
data/librb/engine.rb
CHANGED
|
@@ -3,20 +3,25 @@ require "timers"
|
|
|
3
3
|
require_relative "../src/rulesrb/rules"
|
|
4
4
|
|
|
5
5
|
module Engine
|
|
6
|
-
|
|
6
|
+
@@timers = nil
|
|
7
7
|
class Closure
|
|
8
|
-
attr_reader :handle, :ruleset_name, :_timers, :_branches, :_messages, :_facts, :_retract
|
|
8
|
+
attr_reader :host, :handle, :ruleset_name, :_timers, :_cancelled_timers, :_branches, :_messages, :_queued_messages, :_facts, :_retract
|
|
9
9
|
attr_accessor :s
|
|
10
10
|
|
|
11
|
-
def initialize(state, message, handle, ruleset_name)
|
|
11
|
+
def initialize(host, state, message, handle, ruleset_name)
|
|
12
12
|
@s = Content.new(state)
|
|
13
13
|
@ruleset_name = ruleset_name
|
|
14
14
|
@handle = handle
|
|
15
|
+
@host = host
|
|
15
16
|
@_timers = {}
|
|
17
|
+
@_cancelled_timers = {}
|
|
16
18
|
@_messages = {}
|
|
19
|
+
@_queued_messages = {}
|
|
17
20
|
@_branches = {}
|
|
18
21
|
@_facts = {}
|
|
19
22
|
@_retract = {}
|
|
23
|
+
@_start_time = Time.now
|
|
24
|
+
@_completed = false
|
|
20
25
|
if message.kind_of? Hash
|
|
21
26
|
@m = message
|
|
22
27
|
else
|
|
@@ -53,11 +58,47 @@ module Engine
|
|
|
53
58
|
message_list << message
|
|
54
59
|
end
|
|
55
60
|
|
|
56
|
-
def
|
|
57
|
-
if
|
|
58
|
-
|
|
61
|
+
def queue(ruleset_name, message)
|
|
62
|
+
if message.kind_of? Content
|
|
63
|
+
message = message._d
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if !(message.key? :sid) && !(message.key? "sid")
|
|
67
|
+
message[:sid] = @s.sid
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
message_list = []
|
|
71
|
+
if @_queued_messages.key? ruleset_name
|
|
72
|
+
message_list = @_queued_messages[ruleset_name]
|
|
59
73
|
else
|
|
60
|
-
@
|
|
74
|
+
@_queued_messages[ruleset_name] = message_list
|
|
75
|
+
end
|
|
76
|
+
message_list << message
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def start_timer(timer_name, duration, timer_id = nil)
|
|
80
|
+
if !timer_id
|
|
81
|
+
timer_id = timer_name
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if @_timers.key? timer_id
|
|
85
|
+
raise ArgumentError, "Timer with id #{timer_id} already added"
|
|
86
|
+
else
|
|
87
|
+
timer = {:sid => @s.sid, :id => timer_id, :$t => timer_name}
|
|
88
|
+
@_timers[timer_id] = [timer, duration]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def cancel_timer(timer_name, timer_id = nil)
|
|
93
|
+
if !timer_id
|
|
94
|
+
timer_id = timer_name
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if @_cancelled_timers.key? timer_id
|
|
98
|
+
raise ArgumentError, "Timer with id #{timer_id} already cancelled"
|
|
99
|
+
else
|
|
100
|
+
timer = {:sid => @s.sid, :id => timer_id, :$t => timer_name}
|
|
101
|
+
@_cancelled_timers[timer_id] = timer
|
|
61
102
|
end
|
|
62
103
|
end
|
|
63
104
|
|
|
@@ -107,6 +148,22 @@ module Engine
|
|
|
107
148
|
fact_list << fact
|
|
108
149
|
end
|
|
109
150
|
|
|
151
|
+
def renew_action_lease()
|
|
152
|
+
if Time.now - @_start_time < 10000
|
|
153
|
+
@_start_time = Time.now
|
|
154
|
+
@host.renew_action_lease(@ruleset_name, @s.sid)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def has_completed()
|
|
159
|
+
if Time.now - @_start_time > 10000
|
|
160
|
+
@_completed = true
|
|
161
|
+
end
|
|
162
|
+
value = @_completed
|
|
163
|
+
@_completed = true
|
|
164
|
+
value
|
|
165
|
+
end
|
|
166
|
+
|
|
110
167
|
private
|
|
111
168
|
|
|
112
169
|
def handle_property(name, value=nil)
|
|
@@ -146,7 +203,11 @@ module Engine
|
|
|
146
203
|
def handle_property(name, value=nil)
|
|
147
204
|
name = name.to_s
|
|
148
205
|
if name.end_with? '='
|
|
149
|
-
|
|
206
|
+
if value == nil
|
|
207
|
+
@_d.delete(name[0..-2])
|
|
208
|
+
else
|
|
209
|
+
@_d[name[0..-2]] = value
|
|
210
|
+
end
|
|
150
211
|
nil
|
|
151
212
|
elsif name.end_with? '?'
|
|
152
213
|
@_d.key? name[0..-2]
|
|
@@ -167,12 +228,16 @@ module Engine
|
|
|
167
228
|
|
|
168
229
|
class Promise
|
|
169
230
|
attr_accessor :root
|
|
170
|
-
|
|
171
231
|
def initialize(func)
|
|
172
232
|
@func = func
|
|
173
233
|
@next = nil
|
|
174
234
|
@sync = true
|
|
175
235
|
@root = self
|
|
236
|
+
@timers = Timers::Group.new
|
|
237
|
+
|
|
238
|
+
if func.arity > 1
|
|
239
|
+
@sync = false
|
|
240
|
+
end
|
|
176
241
|
end
|
|
177
242
|
|
|
178
243
|
def continue_with(next_func)
|
|
@@ -193,8 +258,9 @@ module Engine
|
|
|
193
258
|
begin
|
|
194
259
|
@func.call c
|
|
195
260
|
rescue Exception => e
|
|
196
|
-
|
|
197
|
-
|
|
261
|
+
puts "unexpected error #{e}"
|
|
262
|
+
puts e.backtrace
|
|
263
|
+
c.s.exception = e.to_s
|
|
198
264
|
end
|
|
199
265
|
|
|
200
266
|
if @next
|
|
@@ -204,17 +270,37 @@ module Engine
|
|
|
204
270
|
end
|
|
205
271
|
else
|
|
206
272
|
begin
|
|
207
|
-
@func.call c, -> e {
|
|
273
|
+
time_left = @func.call c, -> e {
|
|
208
274
|
if e
|
|
209
|
-
|
|
275
|
+
c.s.exception = e.to_s
|
|
276
|
+
complete.call nil
|
|
210
277
|
elsif @next
|
|
211
278
|
@next.run c, complete
|
|
212
279
|
else
|
|
213
280
|
complete.call nil
|
|
214
281
|
end
|
|
215
282
|
}
|
|
283
|
+
|
|
284
|
+
if time_left && (time_left.kind_of? Integer)
|
|
285
|
+
max_time = Time.now + time_left
|
|
286
|
+
my_timer = @timers.every(5) {
|
|
287
|
+
if Time.now > max_time
|
|
288
|
+
my_timer.cancel
|
|
289
|
+
c.s.exception = "timeout expired"
|
|
290
|
+
complete.call nil
|
|
291
|
+
else
|
|
292
|
+
c.renew_action_lease()
|
|
293
|
+
end
|
|
294
|
+
}
|
|
295
|
+
Thread.new do
|
|
296
|
+
loop { @timers.wait }
|
|
297
|
+
end
|
|
298
|
+
end
|
|
216
299
|
rescue Exception => e
|
|
217
|
-
|
|
300
|
+
puts "unexpected error #{e}"
|
|
301
|
+
puts e.backtrace
|
|
302
|
+
c.s.exception = e.to_s
|
|
303
|
+
complete.call nil
|
|
218
304
|
end
|
|
219
305
|
end
|
|
220
306
|
end
|
|
@@ -296,6 +382,10 @@ module Engine
|
|
|
296
382
|
Rules.assert_event @handle, JSON.generate(message)
|
|
297
383
|
end
|
|
298
384
|
|
|
385
|
+
def queue_event(sid, ruleset_name, message)
|
|
386
|
+
Rules.queue_event @handle, sid.to_s, ruleset_name.to_s, JSON.generate(message)
|
|
387
|
+
end
|
|
388
|
+
|
|
299
389
|
def start_assert_event(message)
|
|
300
390
|
return Rules.start_assert_event @handle, JSON.generate(message)
|
|
301
391
|
end
|
|
@@ -308,11 +398,14 @@ module Engine
|
|
|
308
398
|
return Rules.start_assert_events @handle, JSON.generate(messages)
|
|
309
399
|
end
|
|
310
400
|
|
|
311
|
-
def start_timer(sid,
|
|
312
|
-
timer = {:sid => sid, :id => rand(1000000000), :$t => timer_name}
|
|
401
|
+
def start_timer(sid, timer, timer_duration)
|
|
313
402
|
Rules.start_timer @handle, sid.to_s, timer_duration, JSON.generate(timer)
|
|
314
403
|
end
|
|
315
404
|
|
|
405
|
+
def cancel_timer(sid, timer)
|
|
406
|
+
Rules.cancel_timer @handle, sid.to_s, JSON.generate(timer)
|
|
407
|
+
end
|
|
408
|
+
|
|
316
409
|
def assert_fact(fact)
|
|
317
410
|
Rules.assert_fact @handle, JSON.generate(fact)
|
|
318
411
|
end
|
|
@@ -350,9 +443,13 @@ module Engine
|
|
|
350
443
|
end
|
|
351
444
|
|
|
352
445
|
def get_state(sid)
|
|
353
|
-
JSON.parse Rules.get_state(@handle, sid)
|
|
446
|
+
JSON.parse Rules.get_state(@handle, sid.to_s)
|
|
354
447
|
end
|
|
355
448
|
|
|
449
|
+
def renew_action_lease(sid)
|
|
450
|
+
Rules.renew_action_lease @handle, sid.to_s
|
|
451
|
+
end
|
|
452
|
+
|
|
356
453
|
def Ruleset.create_rulesets(parent_name, host, ruleset_definitions, state_cache_size)
|
|
357
454
|
branches = {}
|
|
358
455
|
for name, definition in ruleset_definitions do
|
|
@@ -385,22 +482,29 @@ module Engine
|
|
|
385
482
|
complete.call nil
|
|
386
483
|
end
|
|
387
484
|
|
|
388
|
-
def dispatch(complete)
|
|
485
|
+
def dispatch(complete, async_result = nil)
|
|
389
486
|
result_container = {}
|
|
390
487
|
action_handle = nil
|
|
391
488
|
action_binding = nil
|
|
392
489
|
state = nil
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
490
|
+
if async_result
|
|
491
|
+
state = async_result[0]
|
|
492
|
+
result_container = {:message => JSON.parse(async_result[1])}
|
|
493
|
+
action_handle = async_result[2]
|
|
494
|
+
action_binding = async_result[3]
|
|
495
|
+
else
|
|
496
|
+
begin
|
|
497
|
+
result = Rules.start_action @handle
|
|
498
|
+
if result
|
|
499
|
+
state = JSON.parse result[0]
|
|
500
|
+
result_container = {:message => JSON.parse(result[1])}
|
|
501
|
+
action_handle = result[2]
|
|
502
|
+
action_binding = result[3]
|
|
503
|
+
end
|
|
504
|
+
rescue Exception => e
|
|
505
|
+
complete.call e
|
|
506
|
+
return
|
|
400
507
|
end
|
|
401
|
-
rescue Exception => e
|
|
402
|
-
complete.call e
|
|
403
|
-
return
|
|
404
508
|
end
|
|
405
509
|
|
|
406
510
|
while result_container.key? :message do
|
|
@@ -410,16 +514,36 @@ module Engine
|
|
|
410
514
|
end
|
|
411
515
|
|
|
412
516
|
result_container.delete :message
|
|
413
|
-
c = Closure.new state, message, action_handle, @name
|
|
517
|
+
c = Closure.new @host, state, message, action_handle, @name
|
|
518
|
+
|
|
519
|
+
if result_container.key? :async
|
|
520
|
+
result_container.delete :async
|
|
521
|
+
end
|
|
522
|
+
|
|
414
523
|
@actions[action_name].run c, -> e {
|
|
524
|
+
if c.has_completed
|
|
525
|
+
return
|
|
526
|
+
end
|
|
527
|
+
|
|
415
528
|
if e
|
|
416
529
|
Rules.abandon_action @handle, c.handle
|
|
417
530
|
complete.call e
|
|
418
531
|
else
|
|
419
532
|
begin
|
|
420
|
-
for
|
|
421
|
-
|
|
533
|
+
for timer_id, timer in c._cancelled_timers do
|
|
534
|
+
cancel_timer c.s.sid, timer
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
for timer_id, timer_duration in c._timers do
|
|
538
|
+
start_timer c.s.sid, timer_duration[0], timer_duration[1]
|
|
422
539
|
end
|
|
540
|
+
|
|
541
|
+
for ruleset_name, messages in c._queued_messages do
|
|
542
|
+
for message in messages do
|
|
543
|
+
queue_event c.s.sid, ruleset_name, message
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
|
|
423
547
|
binding = 0
|
|
424
548
|
replies = 0
|
|
425
549
|
pending = {action_binding => 0}
|
|
@@ -465,6 +589,7 @@ module Engine
|
|
|
465
589
|
else
|
|
466
590
|
pending[binding] = replies
|
|
467
591
|
end
|
|
592
|
+
|
|
468
593
|
for binding, replies in pending do
|
|
469
594
|
if binding != 0
|
|
470
595
|
if binding != action_binding
|
|
@@ -472,17 +597,24 @@ module Engine
|
|
|
472
597
|
else
|
|
473
598
|
new_result = Rules.complete_and_start_action @handle, replies, c.handle
|
|
474
599
|
if new_result
|
|
475
|
-
result_container
|
|
600
|
+
if result_container.key? :async
|
|
601
|
+
dispatch -> e {}, [state, new_result, action_handle, action_binding]
|
|
602
|
+
else
|
|
603
|
+
result_container[:message] = JSON.parse new_result
|
|
604
|
+
end
|
|
476
605
|
end
|
|
477
606
|
end
|
|
478
607
|
end
|
|
479
608
|
end
|
|
480
609
|
rescue Exception => e
|
|
481
610
|
Rules.abandon_action @handle, c.handle
|
|
611
|
+
puts "internal error #{e}"
|
|
612
|
+
puts e.backtrace
|
|
482
613
|
complete.call e
|
|
483
614
|
end
|
|
484
615
|
end
|
|
485
616
|
}
|
|
617
|
+
result_container[:async] = true
|
|
486
618
|
end
|
|
487
619
|
complete.call nil
|
|
488
620
|
end
|
|
@@ -533,8 +665,7 @@ module Engine
|
|
|
533
665
|
if parent_triggers
|
|
534
666
|
for parent_trigger_name, trigger in parent_triggers do
|
|
535
667
|
parent_trigger_name = parent_trigger_name.to_s
|
|
536
|
-
|
|
537
|
-
triggers["#{qualified_name}.#{trigger_name}"] = trigger
|
|
668
|
+
triggers["#{qualified_name}.#{parent_trigger_name}"] = trigger
|
|
538
669
|
end
|
|
539
670
|
end
|
|
540
671
|
|
|
@@ -954,6 +1085,10 @@ module Engine
|
|
|
954
1085
|
get_ruleset(ruleset_name).assert_state state
|
|
955
1086
|
end
|
|
956
1087
|
|
|
1088
|
+
def renew_action_lease(ruleset_name, sid)
|
|
1089
|
+
get_ruleset(ruleset_name).renew_action_lease sid
|
|
1090
|
+
end
|
|
1091
|
+
|
|
957
1092
|
def register_rulesets(parent_name, ruleset_definitions)
|
|
958
1093
|
rulesets = Ruleset.create_rulesets(parent_name, self, ruleset_definitions, @state_cache_size)
|
|
959
1094
|
for ruleset_name, ruleset in rulesets do
|
|
@@ -976,8 +1111,7 @@ module Engine
|
|
|
976
1111
|
dispatch_ruleset = -> c {
|
|
977
1112
|
|
|
978
1113
|
callback = -> e {
|
|
979
|
-
|
|
980
|
-
if index % 10 == 0
|
|
1114
|
+
if index % 5 == 0
|
|
981
1115
|
index += 1
|
|
982
1116
|
timers.after 0.01, &dispatch_ruleset
|
|
983
1117
|
else
|
|
@@ -987,9 +1121,8 @@ module Engine
|
|
|
987
1121
|
}
|
|
988
1122
|
|
|
989
1123
|
timers_callback = -> e {
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
ruleset = @ruleset_list[(index / 10) % @ruleset_list.length]
|
|
1124
|
+
if index % 5 == 0 && @ruleset_list.length > 0
|
|
1125
|
+
ruleset = @ruleset_list[(index / 5) % @ruleset_list.length]
|
|
993
1126
|
ruleset.dispatch_timers callback
|
|
994
1127
|
else
|
|
995
1128
|
callback.call e
|
|
@@ -1004,7 +1137,7 @@ module Engine
|
|
|
1004
1137
|
end
|
|
1005
1138
|
}
|
|
1006
1139
|
|
|
1007
|
-
timers.after 0.
|
|
1140
|
+
timers.after 0.01, &dispatch_ruleset
|
|
1008
1141
|
Thread.new do
|
|
1009
1142
|
loop { timers.wait }
|
|
1010
1143
|
end
|
data/src/rules/events.c
CHANGED
|
@@ -793,7 +793,7 @@ static unsigned int isMatch(ruleset *tree,
|
|
|
793
793
|
*propertyMatch = compareDouble(currentProperty->value.i, rightProperty->value.i, alphaOp);
|
|
794
794
|
break;
|
|
795
795
|
case OP_DOUBLE_DOUBLE:
|
|
796
|
-
*propertyMatch = compareDouble(currentProperty->value.
|
|
796
|
+
*propertyMatch = compareDouble(currentProperty->value.d, rightProperty->value.d, alphaOp);
|
|
797
797
|
break;
|
|
798
798
|
case OP_DOUBLE_STRING:
|
|
799
799
|
{
|
|
@@ -869,7 +869,6 @@ static unsigned int isMatch(ruleset *tree,
|
|
|
869
869
|
if (releaseRightState) {
|
|
870
870
|
free(rightState);
|
|
871
871
|
}
|
|
872
|
-
|
|
873
872
|
return result;
|
|
874
873
|
}
|
|
875
874
|
|
|
@@ -1439,7 +1438,6 @@ static unsigned int handleTimers(void *handle,
|
|
|
1439
1438
|
|
|
1440
1439
|
commands[*commandCount] = command;
|
|
1441
1440
|
++*commandCount;
|
|
1442
|
-
|
|
1443
1441
|
result = handleMessage(handle,
|
|
1444
1442
|
NULL,
|
|
1445
1443
|
reply->element[i]->str,
|
|
@@ -1711,6 +1709,10 @@ unsigned int startAction(void *handle,
|
|
|
1711
1709
|
*state = reply->element[1]->str;
|
|
1712
1710
|
*messages = reply->element[2]->str;
|
|
1713
1711
|
actionContext *context = malloc(sizeof(actionContext));
|
|
1712
|
+
if (!context) {
|
|
1713
|
+
return ERR_OUT_OF_MEMORY;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1714
1716
|
context->reply = reply;
|
|
1715
1717
|
context->rulesBinding = rulesBinding;
|
|
1716
1718
|
*actionHandle = context;
|
|
@@ -1771,7 +1773,12 @@ unsigned int completeAction(void *handle,
|
|
|
1771
1773
|
return result;
|
|
1772
1774
|
}
|
|
1773
1775
|
|
|
1774
|
-
result = executeBatch(rulesBinding, commands, commandCount);
|
|
1776
|
+
result = executeBatch(rulesBinding, commands, commandCount);
|
|
1777
|
+
if (result != RULES_OK) {
|
|
1778
|
+
//reply object should be freed by the app during abandonAction
|
|
1779
|
+
return result;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1775
1782
|
freeReplyObject(reply);
|
|
1776
1783
|
free(actionHandle);
|
|
1777
1784
|
return result;
|
|
@@ -1840,6 +1847,16 @@ unsigned int abandonAction(void *handle, void *actionHandle) {
|
|
|
1840
1847
|
return RULES_OK;
|
|
1841
1848
|
}
|
|
1842
1849
|
|
|
1850
|
+
unsigned int queueMessage(void *handle, char *sid, char *destination, char *message) {
|
|
1851
|
+
void *rulesBinding;
|
|
1852
|
+
unsigned int result = resolveBinding(handle, sid, &rulesBinding);
|
|
1853
|
+
if (result != RULES_OK) {
|
|
1854
|
+
return result;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
return registerMessage(rulesBinding, destination, message);
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1843
1860
|
unsigned int startTimer(void *handle, char *sid, unsigned int duration, char *timer) {
|
|
1844
1861
|
void *rulesBinding;
|
|
1845
1862
|
unsigned int result = resolveBinding(handle, sid, &rulesBinding);
|
|
@@ -1849,3 +1866,24 @@ unsigned int startTimer(void *handle, char *sid, unsigned int duration, char *ti
|
|
|
1849
1866
|
|
|
1850
1867
|
return registerTimer(rulesBinding, duration, timer);
|
|
1851
1868
|
}
|
|
1869
|
+
|
|
1870
|
+
unsigned int cancelTimer(void *handle, char *sid, char *timer) {
|
|
1871
|
+
void *rulesBinding;
|
|
1872
|
+
unsigned int result = resolveBinding(handle, sid, &rulesBinding);
|
|
1873
|
+
if (result != RULES_OK) {
|
|
1874
|
+
return result;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
return removeTimer(rulesBinding, timer);
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
unsigned int renewActionLease(void *handle, char *sid) {
|
|
1881
|
+
void *rulesBinding;
|
|
1882
|
+
unsigned int result = resolveBinding(handle, sid, &rulesBinding);
|
|
1883
|
+
if (result != RULES_OK) {
|
|
1884
|
+
return result;
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
return updateAction(rulesBinding, sid);
|
|
1888
|
+
}
|
|
1889
|
+
|