durable_rules 0.34.06 → 0.34.07

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/librb/engine.rb +152 -85
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 298dc30af9fa87b5556c63f3e9053887fdcec4c7
4
- data.tar.gz: 47c61f7ada560539a88ce3dc1166b535c0f70604
3
+ metadata.gz: f801482db85dfb25b213d116aa0d014cdad42084
4
+ data.tar.gz: 409a2fcaed3552123300f4198d33f4a31fc77cbd
5
5
  SHA512:
6
- metadata.gz: 3f753cbf98f4486f7a08d551d32d7509f9a039ba0b2038e808a9d2ece43ba9c0bc7b9f8e3b1b15791998975e701744f6c80d090f951d33b96f239dd1a4afbf3a
7
- data.tar.gz: 946c9b9283724ded8302763689de2d41d333c2dc869742c07e63464a8d3998e6521aae09a5ba70677b2c850fb7bac3691fb983ec58f8deff9652d14d06c1ad75
6
+ metadata.gz: 93816e1cd7f9da714223c40f358f25e4cee82863617721b9d1e47c46a6054b1a3057851a34db7706b717f34788da8460dedd1e68006614f087c94e82f3e3f251
7
+ data.tar.gz: d8dc3652fc040a1b0f4c255858c89b55652e9870547153eb1d9a7e4d8bed4ff952c3dcac6e2689c9d25edcb729fbfdbead94e0b620aff9231c6cdafd71057625
data/librb/engine.rb CHANGED
@@ -3,11 +3,10 @@ require "timers"
3
3
  require_relative "../src/rulesrb/rules"
4
4
 
5
5
  module Engine
6
- @@timers = nil
7
6
 
8
7
  class Closure_Queue
9
8
  attr_reader :_queued_posts, :_queued_asserts, :_queued_retracts
10
-
9
+
11
10
  def initialize()
12
11
  @_queued_posts = []
13
12
  @_queued_asserts = []
@@ -246,7 +245,7 @@ module Engine
246
245
  def to_s
247
246
  @_d.to_s
248
247
  end
249
-
248
+
250
249
  private
251
250
 
252
251
  def handle_property(name, value=nil)
@@ -283,7 +282,7 @@ module Engine
283
282
  @sync = true
284
283
  @root = self
285
284
  @timers = Timers::Group.new
286
-
285
+
287
286
  if func.arity > 1
288
287
  @sync = false
289
288
  end
@@ -305,13 +304,13 @@ module Engine
305
304
  def run(c, complete)
306
305
  if @sync
307
306
  begin
308
- @func.call c
307
+ @func.call c
309
308
  rescue Exception => e
310
309
  puts "unexpected error #{e}"
311
310
  puts e.backtrace
312
311
  c.s.exception = e.to_s
313
312
  end
314
-
313
+
315
314
  if @next
316
315
  @next.run c, complete
317
316
  else
@@ -350,7 +349,7 @@ module Engine
350
349
  puts e.backtrace
351
350
  c.s.exception = e.to_s
352
351
  complete.call nil
353
- end
352
+ end
354
353
  end
355
354
  end
356
355
 
@@ -368,9 +367,9 @@ module Engine
368
367
  c.retract c.m[0].chart_context
369
368
  else
370
369
  c.retract c.chart_context
371
- end
370
+ end
372
371
  end
373
-
372
+
374
373
  id = rand(1000000000)
375
374
  if assert_state
376
375
  c.assert(:label => to_state, :chart => 1, :id => id)
@@ -410,19 +409,19 @@ module Engine
410
409
  @actions[rule_name] = action.root
411
410
  elsif action.kind_of? Proc
412
411
  @actions[rule_name] = Promise.new action
413
- end
412
+ end
414
413
  end
415
414
 
416
- @handle = Rules.create_ruleset name, JSON.generate(ruleset_definition), state_cache_size
415
+ @handle = Rules.create_ruleset name, JSON.generate(ruleset_definition), state_cache_size
417
416
  @definition = ruleset_definition
418
- end
417
+ end
419
418
 
420
419
  def bind(databases)
421
420
  for db in databases do
422
421
  if db.kind_of? String
423
422
  Rules.bind_ruleset @handle, db, 0, nil
424
- else
425
- Rules.bind_ruleset @handle, db[:host], db[:port], db[:password]
423
+ else
424
+ Rules.bind_ruleset @handle, db[:host], db[:port], db[:password]
426
425
  end
427
426
  end
428
427
  end
@@ -509,11 +508,11 @@ module Engine
509
508
 
510
509
  def renew_action_lease(sid)
511
510
  Rules.renew_action_lease @handle, sid.to_s
512
- end
511
+ end
513
512
 
514
513
  def Ruleset.create_rulesets(parent_name, host, ruleset_definitions, state_cache_size)
515
514
  branches = {}
516
- for name, definition in ruleset_definitions do
515
+ for name, definition in ruleset_definitions do
517
516
  name = name.to_s
518
517
  if name.end_with? "$state"
519
518
  name = name[0..-7]
@@ -529,25 +528,27 @@ module Engine
529
528
  end
530
529
  end
531
530
 
532
- branches
531
+ branches
533
532
  end
534
533
 
535
534
  def dispatch_timers(complete)
536
535
  begin
537
- Rules.assert_timers @handle
536
+ if !(Rules.assert_timers @handle)
537
+ complete.call nil, false
538
+ else
539
+ complete.call nil, true
540
+ end
538
541
  rescue Exception => e
539
- complete.call e
542
+ complete.call e, true
540
543
  return
541
544
  end
542
-
543
- complete.call nil
544
545
  end
545
-
546
+
546
547
  def dispatch(complete, async_result = nil)
547
- result_container = {}
548
+ state = nil
548
549
  action_handle = nil
549
550
  action_binding = nil
550
- state = nil
551
+ result_container = {}
551
552
  if async_result
552
553
  state = async_result[0]
553
554
  result_container = {:message => JSON.parse(async_result[1])}
@@ -556,18 +557,23 @@ module Engine
556
557
  else
557
558
  begin
558
559
  result = Rules.start_action @handle
559
- if result
560
+ if !result
561
+ complete.call nil, true
562
+ return
563
+ else
560
564
  state = JSON.parse result[0]
561
565
  result_container = {:message => JSON.parse(result[1])}
562
566
  action_handle = result[2]
563
567
  action_binding = result[3]
564
568
  end
565
569
  rescue Exception => e
566
- complete.call e
570
+ puts "start action exception #{e}"
571
+ puts e.backtrace
572
+ complete.call e, true
567
573
  return
568
574
  end
569
575
  end
570
-
576
+
571
577
  while result_container.key? :message do
572
578
  action_name = nil
573
579
  for action_name, message in result_container[:message] do
@@ -580,15 +586,15 @@ module Engine
580
586
  if result_container.key? :async
581
587
  result_container.delete :async
582
588
  end
583
-
589
+
584
590
  @actions[action_name].run c, -> e {
585
591
  if c.has_completed
586
592
  return
587
593
  end
588
-
594
+
589
595
  if e
590
596
  Rules.abandon_action @handle, c.handle
591
- complete.call e
597
+ complete.call e, true
592
598
  else
593
599
  begin
594
600
  for timer_id, timer in c._cancelled_timers do
@@ -602,17 +608,17 @@ module Engine
602
608
  for ruleset_name, q in c._queues do
603
609
  for message in q._queued_posts do
604
610
  sid = (message.key? :sid) ? message[:sid]: message['sid']
605
- queue_assert_event sid.to_s, ruleset_name, message
611
+ queue_assert_event sid.to_s, ruleset_name, message
606
612
  end
607
613
 
608
614
  for message in q._queued_asserts do
609
615
  sid = (message.key? :sid) ? message[:sid]: message['sid']
610
- queue_assert_fact sid.to_s, ruleset_name, message
616
+ queue_assert_fact sid.to_s, ruleset_name, message
611
617
  end
612
618
 
613
619
  for message in q._queued_retracts do
614
620
  sid = (message.key? :sid) ? message[:sid]: message['sid']
615
- queue_retract_fact sid.to_s, ruleset_name, message
621
+ queue_retract_fact sid.to_s, ruleset_name, message
616
622
  end
617
623
  end
618
624
 
@@ -674,7 +680,7 @@ module Engine
674
680
  new_result = Rules.complete_and_start_action @handle, replies, c.handle
675
681
  if new_result
676
682
  if result_container.key? :async
677
- dispatch -> e {}, [state, new_result, action_handle, action_binding]
683
+ dispatch -> e, wait {}, [state, new_result, action_handle, action_binding]
678
684
  else
679
685
  result_container[:message] = JSON.parse new_result
680
686
  end
@@ -684,24 +690,24 @@ module Engine
684
690
  end
685
691
  rescue Exception => e
686
692
  Rules.abandon_action @handle, c.handle
687
- puts "internal error #{e}"
693
+ puts "unknown exception #{e}"
688
694
  puts e.backtrace
689
- complete.call e
695
+ complete.call e, true
690
696
  end
691
697
 
692
698
  if c._deleted
693
699
  begin
694
700
  delete_state c.s.sid
695
701
  rescue Exception => e
696
- complete.call e
702
+ complete.call e, true
697
703
  end
698
704
  end
699
705
 
700
706
  end
701
707
  }
702
- result_container[:async] = true
708
+ result_container[:async] = true
703
709
  end
704
- complete.call nil
710
+ complete.call nil, false
705
711
  end
706
712
 
707
713
  def to_json
@@ -725,22 +731,22 @@ module Engine
725
731
  def transform(parent_name, parent_triggers, parent_start_state, chart_definition, rules)
726
732
  start_state = {}
727
733
  reflexive_states = {}
728
-
734
+
729
735
  for state_name, state in chart_definition do
730
736
  qualified_name = state_name.to_s
731
737
  qualified_name = "#{parent_name}.#{state_name}" if parent_name
732
738
  start_state[qualified_name] = true
733
739
 
734
740
  for trigger_name, trigger in state do
735
- if ((trigger.key? :to) && (trigger[:to] == state_name)) ||
736
- ((trigger.key? "to") && (trigger["to"] == state_name)) ||
737
- (trigger.key? :count) || (trigger.key? "count") ||
738
- (trigger.key? :cap) || (trigger.key? "cap") ||
739
- (trigger.key? :span) || (trigger.key? "span")
741
+ if ((trigger.key? :to) && (trigger[:to] == state_name)) ||
742
+ ((trigger.key? "to") && (trigger["to"] == state_name)) ||
743
+ (trigger.key? :count) || (trigger.key? "count") ||
744
+ (trigger.key? :cap) || (trigger.key? "cap") ||
745
+ (trigger.key? :span) || (trigger.key? "span")
740
746
  reflexive_states[qualified_name] = true
741
747
  end
742
748
  end
743
- end
749
+ end
744
750
 
745
751
  for state_name, state in chart_definition do
746
752
  qualified_name = state_name.to_s
@@ -756,7 +762,7 @@ module Engine
756
762
 
757
763
  for trigger_name, trigger in state do
758
764
  trigger_name = trigger_name.to_s
759
- if trigger_name != "$chart"
765
+ if trigger_name != "$chart"
760
766
  if parent_name && (trigger.key? "to")
761
767
  to_name = trigger["to"].to_s
762
768
  trigger["to"] = "#{parent_name}.#{to_name}"
@@ -768,7 +774,7 @@ module Engine
768
774
  end
769
775
  end
770
776
 
771
- if state.key? "$chart"
777
+ if state.key? "$chart"
772
778
  transform qualified_name, triggers, start_state, state["$chart"], rules
773
779
  elsif state.key? :$chart
774
780
  transform qualified_name, triggers, start_state, state[:$chart], rules
@@ -809,7 +815,7 @@ module Engine
809
815
  else
810
816
  all_trigger = trigger["all"]
811
817
  end
812
- rule[:all] = all_trigger.dup
818
+ rule[:all] = all_trigger.dup
813
819
  rule[:all] << state_test
814
820
  elsif (trigger.key? :any) || (trigger.key? "any")
815
821
  any_trigger = nil
@@ -819,10 +825,10 @@ module Engine
819
825
  any_trigger = trigger["any"]
820
826
  end
821
827
  rule[:all] = [state_test, {"m$any" => any_trigger}]
822
- else
828
+ else
823
829
  rule[:all] = [state_test]
824
830
  end
825
-
831
+
826
832
  if (trigger.key? "run") || (trigger.key? :run)
827
833
  trigger_run = nil
828
834
  if trigger.key? :run
@@ -837,7 +843,7 @@ module Engine
837
843
  rule[:run] = trigger_run
838
844
  elsif trigger_run.kind_of? Proc
839
845
  rule[:run] = Promise.new trigger_run
840
- end
846
+ end
841
847
  end
842
848
 
843
849
  if (trigger.key? "to") || (trigger.key? :to)
@@ -917,10 +923,10 @@ module Engine
917
923
  end
918
924
  else
919
925
  for transition_name, transition in stage_to do
920
- if (transition_name == stage_name) ||
921
- (transition.key? :count) || (transition.key? "count") ||
922
- (transition.key? :cap) || (transition.key? "cap") ||
923
- (transition.key? :span) || (transition.key? "span")
926
+ if (transition_name == stage_name) ||
927
+ (transition.key? :count) || (transition.key? "count") ||
928
+ (transition.key? :cap) || (transition.key? "cap") ||
929
+ (transition.key? :span) || (transition.key? "span")
924
930
  reflexive_stages[stage_name] = true
925
931
  end
926
932
  end
@@ -933,7 +939,7 @@ module Engine
933
939
  if reflexive_stages.key? stage_name
934
940
  from_stage = stage_name
935
941
  end
936
-
942
+
937
943
  stage_name = stage_name.to_s
938
944
  stage_test = {:chart_context => {:$and => [{:label => stage_name}, {:chart => 1}]}}
939
945
  if (stage.key? :to) || (stage.key? "to")
@@ -1004,7 +1010,7 @@ module Engine
1004
1010
  else
1005
1011
  all_transition = transition["all"]
1006
1012
  end
1007
- rule[:all] = all_transition.dup
1013
+ rule[:all] = all_transition.dup
1008
1014
  rule[:all] << stage_test
1009
1015
  elsif (transition.key? :any) || (transition.key? "any")
1010
1016
  any_transition = nil
@@ -1014,7 +1020,7 @@ module Engine
1014
1020
  any_transition = transition["any"]
1015
1021
  end
1016
1022
  rule[:all] = [stage_test, {"m$any" => any_transition}]
1017
- else
1023
+ else
1018
1024
  rule[:all] = [stage_test]
1019
1025
  end
1020
1026
 
@@ -1178,7 +1184,7 @@ module Engine
1178
1184
  rulesets = Ruleset.create_rulesets(parent_name, self, ruleset_definitions, @state_cache_size)
1179
1185
  for ruleset_name, ruleset in rulesets do
1180
1186
  if @ruleset_directory.key? ruleset_name
1181
- raise ArgumentError, "Ruleset with name #{ruleset_name} already registered"
1187
+ raise ArgumentError, "Ruleset with name #{ruleset_name} already registered"
1182
1188
  end
1183
1189
 
1184
1190
  @ruleset_directory[ruleset_name] = ruleset
@@ -1190,42 +1196,103 @@ module Engine
1190
1196
  end
1191
1197
 
1192
1198
  def start!
1193
- index = 1
1194
- timers = Timers::Group.new
1195
-
1196
- dispatch_ruleset = -> c {
1197
-
1198
- callback = -> e {
1199
- if index % 5 == 0
1200
- index += 1
1201
- timers.after 0.01, &dispatch_ruleset
1199
+
1200
+ start_dispatch_ruleset_thread
1201
+
1202
+ start_dispatch_timers_thread
1203
+
1204
+ end
1205
+
1206
+ private
1207
+
1208
+ def start_dispatch_timers_thread
1209
+
1210
+ timer = Timers::Group.new
1211
+
1212
+ thread_lambda = -> c {
1213
+
1214
+ callback = -> e, w {
1215
+ inner_wait = Thread.current[:wait]
1216
+ if e
1217
+ puts "unexpected error #{e}"
1218
+ elsif !w
1219
+ inner_wait = false
1220
+ end
1221
+
1222
+ if (Thread.current[:index] == (@ruleset_list.length-1)) & inner_wait
1223
+ Thread.current[:index] = (Thread.current[:index] + 1) % @ruleset_list.length
1224
+ Thread.current[:wait] = inner_wait
1225
+ timer.after 0.25, &thread_lambda
1202
1226
  else
1203
- index += 1
1204
- dispatch_ruleset.call nil
1227
+ Thread.current[:index] = (Thread.current[:index] + 1) % @ruleset_list.length
1228
+ Thread.current[:wait] = inner_wait
1229
+ timer.after 0, &thread_lambda
1205
1230
  end
1206
1231
  }
1207
1232
 
1208
- timers_callback = -> e {
1209
- if index % 5 == 0 && @ruleset_list.length > 0
1210
- ruleset = @ruleset_list[(index / 5) % @ruleset_list.length]
1211
- ruleset.dispatch_timers callback
1233
+ if @ruleset_list.length > 0
1234
+ ruleset = @ruleset_list[Thread.current[:index]]
1235
+ Thread.current[:wait] = true unless Thread.current[:index] > 0
1236
+ ruleset.dispatch_timers callback
1237
+ else
1238
+ timer.after 0.5, &thread_lambda
1239
+ end
1240
+
1241
+ }
1242
+
1243
+ timer.after 0.1, &thread_lambda
1244
+
1245
+ Thread.new do
1246
+ Thread.current[:index] = 0
1247
+ Thread.current[:wait] = 0
1248
+ loop { timer.wait }
1249
+ end
1250
+
1251
+ end
1252
+
1253
+ def start_dispatch_ruleset_thread
1254
+
1255
+ timer = Timers::Group.new
1256
+
1257
+ thread_lambda = -> c {
1258
+
1259
+ callback = -> e, w {
1260
+ inner_wait = Thread.current[:wait]
1261
+ if e
1262
+ puts "unexpected error #{e}"
1263
+ puts e.backtrace
1264
+ elsif !w
1265
+ inner_wait = false
1266
+ end
1267
+ if (Thread.current[:index] == (@ruleset_list.length-1)) & inner_wait
1268
+ Thread.current[:index] = ( Thread.current[:index] + 1 ) % @ruleset_list.length
1269
+ Thread.current[:wait] = inner_wait
1270
+ timer.after 0.25, &thread_lambda
1212
1271
  else
1213
- callback.call e
1272
+ Thread.current[:index] = ( Thread.current[:index] + 1 ) % @ruleset_list.length
1273
+ Thread.current[:wait] = inner_wait
1274
+ timer.after 0, &thread_lambda
1214
1275
  end
1215
1276
  }
1216
1277
 
1217
- if @ruleset_list.length > 0
1218
- ruleset = @ruleset_list[index % @ruleset_list.length]
1219
- ruleset.dispatch timers_callback
1278
+ if @ruleset_list.empty?
1279
+ timer.after 0.5, &thread_lambda
1220
1280
  else
1221
- timers_callback.call nil
1281
+ ruleset = @ruleset_list[Thread.current[:index]]
1282
+ Thread.current[:wait] = true if (Thread.current[:index] > 0)
1283
+ ruleset.dispatch callback
1222
1284
  end
1285
+
1223
1286
  }
1224
1287
 
1225
- timers.after 0.01, &dispatch_ruleset
1288
+ timer.after 0.1, &thread_lambda
1289
+
1226
1290
  Thread.new do
1227
- loop { timers.wait }
1291
+ Thread.current[:index] = 0
1292
+ Thread.current[:wait] = 0
1293
+ loop { timer.wait }
1228
1294
  end
1295
+
1229
1296
  end
1230
1297
 
1231
1298
  end
@@ -1237,11 +1304,11 @@ module Engine
1237
1304
  @handle = Rules.create_client @_ruleset_name, state_cache_size
1238
1305
  if database.kind_of? String
1239
1306
  Rules.bind_ruleset @handle, database, 0, nil
1240
- else
1241
- Rules.bind_ruleset @handle, database[:host], database[:port], database[:password]
1307
+ else
1308
+ Rules.bind_ruleset @handle, database[:host], database[:port], database[:password]
1242
1309
  end
1243
1310
  end
1244
-
1311
+
1245
1312
  def post(message)
1246
1313
  sid = (message.key? :sid) ? message[:sid]: message['sid']
1247
1314
  Rules.queue_assert_event @handle, sid.to_s, @_ruleset_name, JSON.generate(message)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: durable_rules
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.34.06
4
+ version: 0.34.07
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesus Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-14 00:00:00.000000000 Z
11
+ date: 2016-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake