durable_rules 0.31.1
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 +7 -0
- data/LICENSE +20 -0
- data/Rakefile +34 -0
- data/deps/hiredis/COPYING +29 -0
- data/deps/hiredis/Makefile +148 -0
- data/deps/hiredis/async.c +622 -0
- data/deps/hiredis/async.h +125 -0
- data/deps/hiredis/dict.c +338 -0
- data/deps/hiredis/dict.h +126 -0
- data/deps/hiredis/fmacros.h +16 -0
- data/deps/hiredis/hiredis.c +1285 -0
- data/deps/hiredis/hiredis.h +210 -0
- data/deps/hiredis/net.c +299 -0
- data/deps/hiredis/net.h +47 -0
- data/deps/hiredis/sds.c +882 -0
- data/deps/hiredis/sds.h +100 -0
- data/deps/hiredis/test.c +654 -0
- data/deps/hiredis/zmalloc.h +13 -0
- data/librb/durable.rb +549 -0
- data/librb/engine.rb +1015 -0
- data/librb/interface.rb +64 -0
- data/src/rules/Makefile +55 -0
- data/src/rules/events.c +1848 -0
- data/src/rules/json.c +423 -0
- data/src/rules/json.h +24 -0
- data/src/rules/net.c +2559 -0
- data/src/rules/net.h +141 -0
- data/src/rules/rete.c +1726 -0
- data/src/rules/rete.h +133 -0
- data/src/rules/rules.h +171 -0
- data/src/rules/state.c +412 -0
- data/src/rules/state.h +57 -0
- data/src/rulesrb/extconf.rb +37 -0
- data/src/rulesrb/rules.c +644 -0
- metadata +120 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
/* Drop in replacement for zmalloc.h in order to just use libc malloc without
|
2
|
+
* any wrappering. */
|
3
|
+
|
4
|
+
#ifndef ZMALLOC_H
|
5
|
+
#define ZMALLOC_H
|
6
|
+
|
7
|
+
#define zmalloc malloc
|
8
|
+
#define zrealloc realloc
|
9
|
+
#define zcalloc(x) calloc(x,1)
|
10
|
+
#define zfree free
|
11
|
+
#define zstrdup strdup
|
12
|
+
|
13
|
+
#endif
|
data/librb/durable.rb
ADDED
@@ -0,0 +1,549 @@
|
|
1
|
+
require_relative "engine"
|
2
|
+
require_relative "interface"
|
3
|
+
|
4
|
+
module Durable
|
5
|
+
@@rulesets = {}
|
6
|
+
@@start_blocks = []
|
7
|
+
|
8
|
+
def self.run(ruleset_definitions = nil, databases = [{:host => 'localhost', :port => 6379, :password => nil}], start = nil)
|
9
|
+
main_host = Engine::Host.new ruleset_definitions, databases
|
10
|
+
start.call main_host if start
|
11
|
+
main_host.start!
|
12
|
+
Interface::Application.set_host main_host
|
13
|
+
Interface::Application.run!
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.run_all(databases = [{:host => 'localhost', :port => 6379, :password => nil}])
|
17
|
+
main_host = Engine::Host.new @@rulesets, databases
|
18
|
+
for block in @@start_blocks
|
19
|
+
main_host.instance_exec main_host, &block
|
20
|
+
end
|
21
|
+
main_host.start!
|
22
|
+
Interface::Application.set_host main_host
|
23
|
+
Interface::Application.run!
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.ruleset(name, &block)
|
27
|
+
ruleset = Ruleset.new name, block
|
28
|
+
@@rulesets[name] = ruleset.rules
|
29
|
+
@@start_blocks << ruleset.start if ruleset.start
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.statechart(name, &block)
|
33
|
+
statechart = Statechart.new name, block
|
34
|
+
@@rulesets[name.to_s + "$state"] = statechart.states
|
35
|
+
@@start_blocks << statechart.start if statechart.start
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.flowchart(name, &block)
|
39
|
+
flowchart = Flowchart.new name, block
|
40
|
+
@@rulesets[name.to_s + "$flow"] = flowchart.stages
|
41
|
+
@@start_blocks << flowchart.start if flowchart.start
|
42
|
+
end
|
43
|
+
|
44
|
+
class Arithmetic
|
45
|
+
|
46
|
+
def initialize(name, left = nil, sid = nil, op = nil, right = nil)
|
47
|
+
@name = name
|
48
|
+
@left = left
|
49
|
+
@sid = sid
|
50
|
+
@right = right
|
51
|
+
@op = op
|
52
|
+
end
|
53
|
+
|
54
|
+
def definition
|
55
|
+
if not @op
|
56
|
+
if @sid
|
57
|
+
{@name => {:name => @left, :id => @sid}}
|
58
|
+
else
|
59
|
+
{@name => @left}
|
60
|
+
end
|
61
|
+
else
|
62
|
+
new_definition = nil
|
63
|
+
left_definition = nil
|
64
|
+
if @left.kind_of? Arithmetic
|
65
|
+
left_definition = @left.definition
|
66
|
+
else
|
67
|
+
left_definition = {@name => @left}
|
68
|
+
end
|
69
|
+
|
70
|
+
righ_definition = @right
|
71
|
+
if @right.kind_of? Arithmetic
|
72
|
+
righ_definition = @right.definition
|
73
|
+
end
|
74
|
+
|
75
|
+
return {@op => {:$l => left_definition, :$r => righ_definition}}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def +(other)
|
80
|
+
set_right(:$add, other)
|
81
|
+
end
|
82
|
+
|
83
|
+
def -(other)
|
84
|
+
set_right(:$sub, other)
|
85
|
+
end
|
86
|
+
|
87
|
+
def *(other)
|
88
|
+
set_right(:$mul, other)
|
89
|
+
end
|
90
|
+
|
91
|
+
def /(other)
|
92
|
+
set_right(:$div, other)
|
93
|
+
end
|
94
|
+
|
95
|
+
def ==(other)
|
96
|
+
return Expression.new(@name, @left) == other
|
97
|
+
end
|
98
|
+
|
99
|
+
def !=(other)
|
100
|
+
return Expression.new(@name, @left) != other
|
101
|
+
end
|
102
|
+
|
103
|
+
def <(other)
|
104
|
+
return Expression.new(@name, @left) < other
|
105
|
+
end
|
106
|
+
|
107
|
+
def <=(other)
|
108
|
+
return Expression.new(@name, @left) <= other
|
109
|
+
end
|
110
|
+
|
111
|
+
def >(other)
|
112
|
+
return Expression.new(@name, @left) > other
|
113
|
+
end
|
114
|
+
|
115
|
+
def >=(other)
|
116
|
+
return Expression.new(@name, @left) >= other
|
117
|
+
end
|
118
|
+
|
119
|
+
def -@
|
120
|
+
return -Expression.new(@name, @left)
|
121
|
+
end
|
122
|
+
|
123
|
+
def +@
|
124
|
+
return +Expression.new(@name, @left)
|
125
|
+
end
|
126
|
+
|
127
|
+
def |(other)
|
128
|
+
return Expression.new(@name, @left) | other
|
129
|
+
end
|
130
|
+
|
131
|
+
def &(other)
|
132
|
+
return Expression.new(@name, @left) & other
|
133
|
+
end
|
134
|
+
|
135
|
+
def id(sid)
|
136
|
+
Arithmetic.new @name, @left, sid
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def set_right(op, other)
|
142
|
+
if @right
|
143
|
+
@left = Arithmetic.new @name, @left, @sid, @op, @right
|
144
|
+
end
|
145
|
+
|
146
|
+
@op = op
|
147
|
+
@right = other
|
148
|
+
self
|
149
|
+
end
|
150
|
+
|
151
|
+
def default(name, value=nil)
|
152
|
+
@left = name
|
153
|
+
self
|
154
|
+
end
|
155
|
+
|
156
|
+
alias method_missing default
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
class Expression
|
161
|
+
attr_reader :__type, :__op
|
162
|
+
attr_accessor :__name
|
163
|
+
|
164
|
+
def initialize(type, left = nil)
|
165
|
+
@__type = type
|
166
|
+
@left = left
|
167
|
+
@right = nil
|
168
|
+
@definitions = nil
|
169
|
+
@__name = nil
|
170
|
+
end
|
171
|
+
|
172
|
+
def definition
|
173
|
+
new_definition = nil
|
174
|
+
if @__op == :$or || @__op == :$and
|
175
|
+
new_definition = {@__op => @definitions}
|
176
|
+
else
|
177
|
+
if not @left
|
178
|
+
raise ArgumentError, "Property for #{@__op} not defined"
|
179
|
+
end
|
180
|
+
righ_definition = @right
|
181
|
+
if (@right.kind_of? Expression) || (@right.kind_of? Arithmetic)
|
182
|
+
righ_definition = @right.definition
|
183
|
+
end
|
184
|
+
|
185
|
+
if @__op == :$eq
|
186
|
+
new_definition = {@left => righ_definition}
|
187
|
+
else
|
188
|
+
new_definition = {@__op => {@left => righ_definition}}
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
if @__type == :$s
|
193
|
+
{:$and => [new_definition, {:$s => 1}]}
|
194
|
+
else
|
195
|
+
new_definition
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def ==(other)
|
200
|
+
@__op = :$eq
|
201
|
+
@right = other
|
202
|
+
self
|
203
|
+
end
|
204
|
+
|
205
|
+
def !=(other)
|
206
|
+
@__op = :$neq
|
207
|
+
@right = other
|
208
|
+
self
|
209
|
+
end
|
210
|
+
|
211
|
+
def <(other)
|
212
|
+
@__op = :$lt
|
213
|
+
@right = other
|
214
|
+
self
|
215
|
+
end
|
216
|
+
|
217
|
+
def <=(other)
|
218
|
+
@__op = :$lte
|
219
|
+
@right = other
|
220
|
+
self
|
221
|
+
end
|
222
|
+
|
223
|
+
def >(other)
|
224
|
+
@__op = :$gt
|
225
|
+
@right = other
|
226
|
+
self
|
227
|
+
end
|
228
|
+
|
229
|
+
def >=(other)
|
230
|
+
@__op = :$gte
|
231
|
+
@right = other
|
232
|
+
self
|
233
|
+
end
|
234
|
+
|
235
|
+
def -@
|
236
|
+
@__op = :$nex
|
237
|
+
@right = 1
|
238
|
+
self
|
239
|
+
end
|
240
|
+
|
241
|
+
def +@
|
242
|
+
@__op = :$ex
|
243
|
+
@right = 1
|
244
|
+
self
|
245
|
+
end
|
246
|
+
|
247
|
+
def |(other)
|
248
|
+
merge other, :$or
|
249
|
+
self
|
250
|
+
end
|
251
|
+
|
252
|
+
def &(other)
|
253
|
+
merge other, :$and
|
254
|
+
self
|
255
|
+
end
|
256
|
+
|
257
|
+
private
|
258
|
+
|
259
|
+
def default(name, value=nil)
|
260
|
+
@left = name
|
261
|
+
self
|
262
|
+
end
|
263
|
+
|
264
|
+
def merge(other, op)
|
265
|
+
raise ArgumentError, "Right type doesn't match" if other.__type != @__type
|
266
|
+
@definitions = [self.definition] if !@definitions
|
267
|
+
@__op = op
|
268
|
+
if other.__op && (other.__op == @__op)
|
269
|
+
@definitions + other.definition[@__op]
|
270
|
+
else
|
271
|
+
@definitions << other.definition
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
alias method_missing default
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
class Expressions
|
280
|
+
attr_reader :__type
|
281
|
+
|
282
|
+
def initialize(type, expressions)
|
283
|
+
@__type = type
|
284
|
+
@expressions = expressions
|
285
|
+
end
|
286
|
+
|
287
|
+
def definition
|
288
|
+
index = 0
|
289
|
+
new_definition = []
|
290
|
+
for expression in @expressions do
|
291
|
+
if (expression.kind_of? Expression) && expression.__name
|
292
|
+
expression_name = expression.__name
|
293
|
+
elsif @expressions.length == 1
|
294
|
+
expression_name = "m"
|
295
|
+
else
|
296
|
+
expression_name = "m_#{index}"
|
297
|
+
end
|
298
|
+
if expression.__type == :$all
|
299
|
+
new_definition << {expression_name + "$all" => expression.definition()}
|
300
|
+
elsif expression.__type == :$any
|
301
|
+
new_definition << {expression_name + "$any" => expression.definition()}
|
302
|
+
elsif expression.__type == :$not
|
303
|
+
new_definition << {expression_name + "$not" => expression.definition()[0]["m"]}
|
304
|
+
else
|
305
|
+
new_definition << {expression_name => expression.definition()}
|
306
|
+
end
|
307
|
+
index += 1
|
308
|
+
end
|
309
|
+
new_definition
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
class Closure
|
315
|
+
|
316
|
+
def s
|
317
|
+
Arithmetic.new(:$s)
|
318
|
+
end
|
319
|
+
|
320
|
+
private
|
321
|
+
|
322
|
+
def handle_property(name, value=nil)
|
323
|
+
name = name.to_s
|
324
|
+
if name.end_with? '='
|
325
|
+
name = name[0..-2]
|
326
|
+
value.__name = name
|
327
|
+
return value
|
328
|
+
else
|
329
|
+
Arithmetic.new(name)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
alias method_missing handle_property
|
334
|
+
end
|
335
|
+
|
336
|
+
class Ruleset
|
337
|
+
attr_reader :name, :start
|
338
|
+
attr_accessor :rules
|
339
|
+
|
340
|
+
def initialize(name, block)
|
341
|
+
@name = name
|
342
|
+
@rules = {}
|
343
|
+
@rule_index = 0
|
344
|
+
@expression_index = 0
|
345
|
+
@start = nil
|
346
|
+
self.instance_exec &block
|
347
|
+
end
|
348
|
+
|
349
|
+
def when_all(*args, &block)
|
350
|
+
options, new_args = get_options(*args)
|
351
|
+
define_rule :all, Expressions.new(:$all, new_args).definition, options, &block
|
352
|
+
end
|
353
|
+
|
354
|
+
def when_any(*args, &block)
|
355
|
+
options, new_args = get_options(*args)
|
356
|
+
define_rule :any, Expressions.new(:$any, new_args).definition, options, &block
|
357
|
+
end
|
358
|
+
|
359
|
+
def all(*args)
|
360
|
+
Expressions.new :$all, args
|
361
|
+
end
|
362
|
+
|
363
|
+
def any(*args)
|
364
|
+
Expressions.new :$any, args
|
365
|
+
end
|
366
|
+
|
367
|
+
def none(*args)
|
368
|
+
Expressions.new :$not, args
|
369
|
+
end
|
370
|
+
|
371
|
+
def when_start(&block)
|
372
|
+
@start = block
|
373
|
+
self
|
374
|
+
end
|
375
|
+
|
376
|
+
def s
|
377
|
+
Arithmetic.new(:$s)
|
378
|
+
end
|
379
|
+
|
380
|
+
def m
|
381
|
+
Expression.new(:$m)
|
382
|
+
end
|
383
|
+
|
384
|
+
def c
|
385
|
+
Closure.new()
|
386
|
+
end
|
387
|
+
|
388
|
+
def count(value)
|
389
|
+
{:count => value}
|
390
|
+
end
|
391
|
+
|
392
|
+
def pri(value)
|
393
|
+
{:pri => value}
|
394
|
+
end
|
395
|
+
|
396
|
+
def span(value)
|
397
|
+
{:span => value}
|
398
|
+
end
|
399
|
+
|
400
|
+
def cap(value)
|
401
|
+
{:cap => value}
|
402
|
+
end
|
403
|
+
|
404
|
+
def timeout(name)
|
405
|
+
expression = Expression.new(:$m, :$t)
|
406
|
+
expression == name
|
407
|
+
end
|
408
|
+
|
409
|
+
protected
|
410
|
+
|
411
|
+
def get_options(*args)
|
412
|
+
options = {}
|
413
|
+
new_args = []
|
414
|
+
for arg in args do
|
415
|
+
if arg.kind_of? Hash
|
416
|
+
options = options.merge!(arg)
|
417
|
+
else
|
418
|
+
new_args << arg
|
419
|
+
end
|
420
|
+
end
|
421
|
+
return options, new_args
|
422
|
+
end
|
423
|
+
|
424
|
+
def define_rule(operator, expression_definition, options, &block)
|
425
|
+
index = @rule_index.to_s
|
426
|
+
@rule_index += 1
|
427
|
+
rule_name = "r_#{index}"
|
428
|
+
rule = nil
|
429
|
+
if block
|
430
|
+
run_lambda = -> c {
|
431
|
+
c.instance_exec c, &block
|
432
|
+
}
|
433
|
+
rule = operator ? {operator => expression_definition, :run => run_lambda} : {:run => run_lambda}
|
434
|
+
else
|
435
|
+
rule = operator ? {operator => expression_definition} : {}
|
436
|
+
end
|
437
|
+
|
438
|
+
if options.key? :count
|
439
|
+
rule["count"] = options[:count]
|
440
|
+
end
|
441
|
+
|
442
|
+
if options.key? :pri
|
443
|
+
rule["pri"] = options[:pri]
|
444
|
+
end
|
445
|
+
|
446
|
+
if options.key? :span
|
447
|
+
rule["span"] = options[:span]
|
448
|
+
end
|
449
|
+
|
450
|
+
if options.key? :cap
|
451
|
+
rule["cap"] = options[:cap]
|
452
|
+
end
|
453
|
+
|
454
|
+
@rules[rule_name] = rule
|
455
|
+
rule
|
456
|
+
end
|
457
|
+
|
458
|
+
private
|
459
|
+
|
460
|
+
def handle_property(name, value=nil)
|
461
|
+
return Arithmetic.new(name.to_s)
|
462
|
+
end
|
463
|
+
|
464
|
+
alias method_missing handle_property
|
465
|
+
|
466
|
+
end
|
467
|
+
|
468
|
+
|
469
|
+
class State < Ruleset
|
470
|
+
|
471
|
+
def initialize(name, block)
|
472
|
+
super name, block
|
473
|
+
end
|
474
|
+
|
475
|
+
def to(state_name, rule = nil, &block)
|
476
|
+
rule = define_rule(nil, nil, {}, &block) if !rule
|
477
|
+
rule[:to] = state_name
|
478
|
+
if block
|
479
|
+
rule[:run] = -> s {s.instance_exec(s, &block)}
|
480
|
+
end
|
481
|
+
self
|
482
|
+
end
|
483
|
+
|
484
|
+
def state(state_name, &block)
|
485
|
+
@rules[:$chart] = {} if (!@rules.key? :$chart)
|
486
|
+
if block
|
487
|
+
@rules[:$chart][state_name] = State.new(state_name, block).rules
|
488
|
+
else
|
489
|
+
@rules[:$chart][state_name] = {}
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
end
|
494
|
+
|
495
|
+
class Statechart
|
496
|
+
attr_reader :states, :start
|
497
|
+
|
498
|
+
def initialize(name, block)
|
499
|
+
@states = {}
|
500
|
+
self.instance_exec &block
|
501
|
+
end
|
502
|
+
|
503
|
+
def state(state_name, &block)
|
504
|
+
if block
|
505
|
+
states[state_name] = State.new(state_name, block).rules
|
506
|
+
else
|
507
|
+
states[state_name] = {}
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
def when_start(&block)
|
512
|
+
@start = block
|
513
|
+
self
|
514
|
+
end
|
515
|
+
|
516
|
+
end
|
517
|
+
|
518
|
+
class Flowchart < Ruleset
|
519
|
+
attr_reader :stages
|
520
|
+
|
521
|
+
def initialize(name, block)
|
522
|
+
@stages = {}
|
523
|
+
@current_stage = nil
|
524
|
+
super name, block
|
525
|
+
end
|
526
|
+
|
527
|
+
def to(stage_name, rule = nil)
|
528
|
+
if !rule
|
529
|
+
stages[@current_stage][:to] = stage_name
|
530
|
+
elsif rule.key? :all
|
531
|
+
stages[@current_stage][:to][stage_name] = {:all => rule[:all]}
|
532
|
+
else
|
533
|
+
stages[@current_stage][:to][stage_name] = {:any => rule[:any]}
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
def stage(stage_name, &block)
|
538
|
+
if block
|
539
|
+
@stages[stage_name] = {:run => -> s {s.instance_exec(s, &block)}, :to => {}}
|
540
|
+
else
|
541
|
+
@stages[stage_name] = {:to => {}}
|
542
|
+
end
|
543
|
+
|
544
|
+
@current_stage = stage_name
|
545
|
+
self
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
end
|