durable_rules 0.33.13 → 0.34.01
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|