durable_rules 0.34.10 → 0.34.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 17af99e481ae4e0bcb1b2ebe209b6e5edc18fee9
4
- data.tar.gz: cb8dd76e247553ece6ddc1e07b55c73185472a84
3
+ metadata.gz: 1a1c33ac9771e6fd5a65c237fa9ec44043ee2efa
4
+ data.tar.gz: 92da33c1378bccefc450cf31d0bbff11301fa2e8
5
5
  SHA512:
6
- metadata.gz: 6e850df050e57f8d9c3a6afe9e95290dcda77a15822b653b0a4dd65dfc379ebf2f78fcf3139a84817250671031ef502ff3aa53c6ebb9d637d8c08ba972c7ab5f
7
- data.tar.gz: 11c23e9dffe070addf470d6a5535dc4c964892c1674a047981c525009614ca5134af25b2553152885483542c3403285692da9fd013f32a17ccde565a1ef4c739
6
+ metadata.gz: e1557c00a12d9eff3c8d4d0b35c0e6efacf2928f2e1435eb873978e279af3a2f6f9f3b33d82bae98a2a10607469bf218ec942cc6a106f13cc5115d3c12ddb429
7
+ data.tar.gz: def1bedb13771e6f5546c5043933019cb36f1706293eb8afd79d97a05803dad5366765e085d87098aaa271a4d2e7b5834aeb261aed8bfad84f2b89f7b4893ec8
data/librb/durable.rb CHANGED
@@ -178,7 +178,7 @@ module Durable
178
178
  @__name = nil
179
179
  end
180
180
 
181
- def definition
181
+ def definition(parent_name=nil)
182
182
  new_definition = nil
183
183
  if @__op == :$or || @__op == :$and
184
184
  new_definition = {@__op => @definitions}
@@ -297,25 +297,33 @@ module Durable
297
297
  @expressions = expressions
298
298
  end
299
299
 
300
- def definition
300
+ def definition(parent_name=nil)
301
301
  index = 0
302
302
  new_definition = []
303
303
  for expression in @expressions do
304
304
  if (expression.kind_of? Expression) && expression.__name
305
305
  expression_name = expression.__name
306
306
  elsif @expressions.length == 1
307
- expression_name = "m"
307
+ if parent_name
308
+ expression_name = "#{parent_name}.m"
309
+ else
310
+ expression_name = "m"
311
+ end
308
312
  else
309
- expression_name = "m_#{index}"
313
+ if parent_name
314
+ expression_name = "#{parent_name}.m_#{index}"
315
+ else
316
+ expression_name = "m_#{index}"
317
+ end
310
318
  end
311
319
  if expression.__type == :$all
312
- new_definition << {expression_name + "$all" => expression.definition()}
320
+ new_definition << {expression_name + "$all" => expression.definition(expression_name)}
313
321
  elsif expression.__type == :$any
314
- new_definition << {expression_name + "$any" => expression.definition()}
322
+ new_definition << {expression_name + "$any" => expression.definition(expression_name)}
315
323
  elsif expression.__type == :$not
316
324
  new_definition << {expression_name + "$not" => expression.definition()[0]["m"]}
317
325
  else
318
- new_definition << {expression_name => expression.definition()}
326
+ new_definition << {expression_name => expression.definition(expression_name)}
319
327
  end
320
328
  index += 1
321
329
  end
data/librb/engine.rb CHANGED
@@ -495,7 +495,11 @@ module Engine
495
495
  end
496
496
 
497
497
  def assert_state(state)
498
- Rules.assert_state @handle, JSON.generate(state)
498
+ if state.key? :sid
499
+ Rules.assert_state @handle, state[:sid].to_s, JSON.generate(state)
500
+ else
501
+ Rules.assert_state @handle, state["sid"].to_s, JSON.generate(state)
502
+ end
499
503
  end
500
504
 
501
505
  def get_state(sid)
data/src/rules/events.c CHANGED
@@ -33,6 +33,7 @@
33
33
  #define OP_STRING_STRING 0x0101
34
34
 
35
35
  typedef struct actionContext {
36
+ unsigned long stateVersion;
36
37
  void *rulesBinding;
37
38
  redisReply *reply;
38
39
  } actionContext;
@@ -1029,6 +1030,7 @@ static unsigned int handleMessageCore(ruleset *tree,
1029
1030
  jsonProperty *sidProperty;
1030
1031
  int sidLength;
1031
1032
  char *storeCommand;
1033
+ char *versionCommand;
1032
1034
  int result = getId(properties, sidIndex, &sidProperty, &sidLength);
1033
1035
  if (result != RULES_OK) {
1034
1036
  return result;
@@ -1064,17 +1066,20 @@ static unsigned int handleMessageCore(ruleset *tree,
1064
1066
  }
1065
1067
  }
1066
1068
 
1067
- if (*commandCount == MAX_COMMAND_COUNT) {
1068
- return ERR_MAX_COMMAND_COUNT;
1069
- }
1070
-
1071
- result = formatStoreSession(*rulesBinding, sid, state, 0, &storeCommand);
1069
+ result = formatStoreSession(*rulesBinding, sid, state, 0, &storeCommand, &versionCommand);
1072
1070
  if (result != RULES_OK) {
1073
1071
  return result;
1074
1072
  }
1075
1073
 
1076
1074
  commands[*commandCount] = storeCommand;
1077
1075
  ++*commandCount;
1076
+
1077
+ if (*commandCount == MAX_COMMAND_COUNT) {
1078
+ return ERR_MAX_COMMAND_COUNT;
1079
+ }
1080
+
1081
+ commands[*commandCount] = versionCommand;
1082
+ ++*commandCount;
1078
1083
  }
1079
1084
  char *removeCommand = NULL;
1080
1085
  char *addKeys[MAX_ADD_COUNT];
@@ -1220,7 +1225,7 @@ static unsigned int handleMessageCore(ruleset *tree,
1220
1225
  return ERR_MAX_COMMAND_COUNT;
1221
1226
  }
1222
1227
 
1223
- result = formatStoreSession(*rulesBinding, sid, newState, 1, &storeCommand);
1228
+ result = formatStoreSession(*rulesBinding, sid, newState, 1, &storeCommand, &versionCommand);
1224
1229
  if (result != RULES_OK) {
1225
1230
  return result;
1226
1231
  }
@@ -1228,6 +1233,13 @@ static unsigned int handleMessageCore(ruleset *tree,
1228
1233
  commands[*commandCount] = storeCommand;
1229
1234
  ++*commandCount;
1230
1235
 
1236
+ if (*commandCount == MAX_COMMAND_COUNT) {
1237
+ return ERR_MAX_COMMAND_COUNT;
1238
+ }
1239
+
1240
+ commands[*commandCount] = versionCommand;
1241
+ ++*commandCount;
1242
+
1231
1243
  result = handleMessage(tree,
1232
1244
  NULL,
1233
1245
  stateMessage,
@@ -1362,7 +1374,8 @@ static unsigned int handleMessages(void *handle,
1362
1374
  }
1363
1375
 
1364
1376
  static unsigned int handleState(ruleset *tree,
1365
- char *state,
1377
+ char *state,
1378
+ unsigned long stateVersion,
1366
1379
  char **commands,
1367
1380
  unsigned int *commandCount,
1368
1381
  void **rulesBinding) {
@@ -1377,15 +1390,15 @@ static unsigned int handleState(ruleset *tree,
1377
1390
 
1378
1391
  char *stateMessagePostfix = state + 1;
1379
1392
  #ifdef _WIN32
1380
- char *stateMessage = (char *)_alloca(sizeof(char)*(35 + stateLength - 1));
1393
+ char *stateMessage = (char *)_alloca(sizeof(char)*(40 + stateLength - 1));
1381
1394
  #else
1382
- char stateMessage[35 + stateLength - 1];
1395
+ char stateMessage[40 + stateLength - 1];
1383
1396
  #endif
1384
- int randomMid = rand();
1397
+
1385
1398
  #ifdef _WIN32
1386
- sprintf_s(stateMessage, 35 + stateLength - 1, "{\"id\":\"$v-%d\", \"$s\":1, %s", randomMid, stateMessagePostfix);
1399
+ sprintf_s(stateMessage, 40 + stateLength - 1, "{\"id\":\"$v-%016lu\", \"$s\":1, %s", stateVersion, stateMessagePostfix);
1387
1400
  #else
1388
- snprintf(stateMessage, 35 + stateLength - 1, "{\"id\":\"$v-%d\", \"$s\":1, %s", randomMid, stateMessagePostfix);
1401
+ snprintf(stateMessage, 40 + stateLength - 1, "{\"id\":\"$v-%016lu\", \"$s\":1, %s", stateVersion, stateMessagePostfix);
1389
1402
  #endif
1390
1403
  unsigned int result = handleMessage(tree,
1391
1404
  state,
@@ -1638,15 +1651,22 @@ unsigned int startRetractFacts(void *handle,
1638
1651
  return startHandleMessages(handle, messages, ACTION_REMOVE_FACT, rulesBinding, replyCount);
1639
1652
  }
1640
1653
 
1641
- unsigned int assertState(void *handle, char *state) {
1654
+ unsigned int assertState(void *handle, char *sid, char *state) {
1642
1655
  char *commands[MAX_COMMAND_COUNT];
1643
1656
  unsigned int commandCount = 0;
1644
1657
  void *rulesBinding = NULL;
1645
- unsigned int result = handleState(handle,
1646
- state,
1647
- commands,
1648
- &commandCount,
1649
- &rulesBinding);
1658
+ unsigned long stateVersion;
1659
+ unsigned int result = getStateVersion(handle, sid, &stateVersion);
1660
+ if (result != RULES_OK) {
1661
+ return result;
1662
+ }
1663
+
1664
+ result = handleState(handle,
1665
+ state,
1666
+ stateVersion,
1667
+ commands,
1668
+ &commandCount,
1669
+ &rulesBinding);
1650
1670
  if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
1651
1671
  freeCommands(commands, commandCount);
1652
1672
  return result;
@@ -1693,13 +1713,14 @@ unsigned int startAction(void *handle,
1693
1713
  return result;
1694
1714
  }
1695
1715
 
1696
- *state = reply->element[1]->str;
1697
- *messages = reply->element[2]->str;
1716
+ *state = reply->element[2]->str;
1717
+ *messages = reply->element[3]->str;
1698
1718
  actionContext *context = malloc(sizeof(actionContext));
1699
1719
  if (!context) {
1700
1720
  return ERR_OUT_OF_MEMORY;
1701
1721
  }
1702
1722
 
1723
+ context->stateVersion = reply->element[1]->integer;
1703
1724
  context->reply = reply;
1704
1725
  context->rulesBinding = rulesBinding;
1705
1726
  *actionHandle = context;
@@ -1715,8 +1736,10 @@ unsigned int startUpdateState(void *handle,
1715
1736
  char *commands[MAX_COMMAND_COUNT];
1716
1737
  unsigned int result = RULES_OK;
1717
1738
  unsigned int commandCount = 0;
1739
+ unsigned long stateVersion = ((actionContext*)actionHandle)->stateVersion;
1718
1740
  result = handleState(handle,
1719
1741
  state,
1742
+ stateVersion,
1720
1743
  commands,
1721
1744
  &commandCount,
1722
1745
  rulesBinding);
@@ -1750,7 +1773,8 @@ unsigned int completeAction(void *handle,
1750
1773
 
1751
1774
  ++commandCount;
1752
1775
  result = handleState(handle,
1753
- state,
1776
+ state,
1777
+ context->stateVersion,
1754
1778
  commands,
1755
1779
  &commandCount,
1756
1780
  &rulesBinding);
@@ -1823,7 +1847,8 @@ unsigned int completeAndStartAction(void *handle,
1823
1847
  return ERR_NO_ACTION_AVAILABLE;
1824
1848
  }
1825
1849
 
1826
- *messages = newReply->element[1]->str;
1850
+ *messages = newReply->element[2]->str;
1851
+ context->stateVersion = newReply->element[1]->integer;
1827
1852
  context->reply = newReply;
1828
1853
  return RULES_OK;
1829
1854
  }
data/src/rules/net.c CHANGED
@@ -528,11 +528,13 @@ static unsigned int loadDeleteSessionCommand(ruleset *tree, binding *rulesBindin
528
528
  " end\n"
529
529
  "end\n"
530
530
  "redis.call(\"hdel\", \"%s!s\", sid)\n"
531
+ "redis.call(\"hdel\", \"%s!s!v\", sid)\n"
531
532
  "redis.call(\"zrem\", \"%s!a\", sid)\n"
532
533
  "redis.call(\"del\", \"%s!a!\" .. sid)\n"
533
534
  "redis.call(\"del\", \"%s!e!\" .. sid)\n"
534
535
  "redis.call(\"del\", \"%s!f!\" .. sid)\n"
535
536
  "redis.call(\"del\", \"%s!v!\" .. sid)\n%s",
537
+ name,
536
538
  name,
537
539
  name,
538
540
  name,
@@ -661,6 +663,10 @@ static unsigned int loadAddMessageCommand(ruleset *tree, binding *rulesBinding)
661
663
  " else\n"
662
664
  " message[ARGV[index]] = false\n"
663
665
  " end\n"
666
+ " elseif ARGV[index + 2] == \"5\" then\n"
667
+ " message[ARGV[index]] = cjson.decode(ARGV[index + 1])\n"
668
+ " elseif ARGV[index + 2] == \"7\" then\n"
669
+ " message[ARGV[index]] = \"$null\"\n"
664
670
  " end\n"
665
671
  "end\n"
666
672
  "local mid = message[\"id\"]\n"
@@ -763,8 +769,9 @@ static unsigned int loadPeekActionCommand(ruleset *tree, binding *rulesBinding)
763
769
  for (unsigned int iii = 0; iii < currentJoin->expressionsLength; ++iii) {
764
770
  unsigned int expressionOffset = tree->nextPool[currentJoin->expressionsOffset + iii];
765
771
  expression *expr = &tree->expressionPool[expressionOffset];
766
- char *currentAlias = &tree->stringPool[expr->aliasOffset];
767
772
  char *currentKey = &tree->stringPool[expr->nameOffset];
773
+ char *currentAlias = &tree->stringPool[expr->aliasOffset];
774
+
768
775
 
769
776
  if (iii == 0) {
770
777
  if (expr->not) {
@@ -1083,13 +1090,23 @@ static unsigned int loadPeekActionCommand(ruleset *tree, binding *rulesBinding)
1083
1090
  " return sid, name, frame\n"
1084
1091
  "end\n"
1085
1092
  "local fixup_frame = function(frame)\n"
1093
+ " local new_frame = {}\n"
1086
1094
  " for message_name, message in pairs(frame) do\n"
1087
- " if message ~= \"$n\" then\n"
1095
+ " if message_name == 1 then\n"
1096
+ " return frame\n"
1097
+ " end\n"
1098
+ " local start\n"
1099
+ " local name\n"
1100
+ " local next\n"
1101
+ " local new_message = {}\n"
1102
+ " if message == \"$n\" then\n"
1103
+ " new_message = message\n"
1104
+ " else\n"
1088
1105
  " for key, value in pairs(message) do\n"
1089
- " local start = 1\n"
1090
- " local sub_message = message\n"
1091
- " local name = key\n"
1092
- " local next = nil\n"
1106
+ " local sub_message = new_message\n"
1107
+ " start = 1\n"
1108
+ " name = key\n"
1109
+ " next = nil\n"
1093
1110
  " repeat\n"
1094
1111
  " next = string.find(key, \"%%.\", start)\n"
1095
1112
  " if next then\n"
@@ -1106,12 +1123,36 @@ static unsigned int loadPeekActionCommand(ruleset *tree, binding *rulesBinding)
1106
1123
  " name = string.sub(key, start)\n"
1107
1124
  " end\n"
1108
1125
  " until not next\n"
1109
- " message[key] = nil\n"
1110
- " sub_message[name] = value\n"
1126
+ " if value == \"$null\" then\n"
1127
+ " sub_message[name] = cjson.null\n"
1128
+ " else\n"
1129
+ " sub_message[name] = value\n"
1130
+ " end\n"
1111
1131
  " end\n"
1112
1132
  " end\n"
1133
+ " local sub_frame = new_frame\n"
1134
+ " name = message_name\n"
1135
+ " next = nil\n"
1136
+ " start = 1\n"
1137
+ " repeat\n"
1138
+ " next = string.find(message_name, \"%%.\", start)\n"
1139
+ " if next then\n"
1140
+ " name = string.sub(message_name, start, next - 1)\n"
1141
+ " if sub_frame[name] then\n"
1142
+ " sub_frame = sub_frame[name]\n"
1143
+ " else\n"
1144
+ " local new_sub_frame = {}\n"
1145
+ " sub_frame[name] = new_sub_frame\n"
1146
+ " sub_frame = new_sub_frame\n"
1147
+ " end\n"
1148
+ " start = next + 1\n"
1149
+ " else\n"
1150
+ " name = string.sub(message_name, start)\n"
1151
+ " end\n"
1152
+ " until not next\n"
1153
+ " sub_frame[name] = new_message\n"
1113
1154
  " end\n"
1114
- " return frame\n"
1155
+ " return new_frame\n"
1115
1156
  "end\n"
1116
1157
  "get_context = function(action_key)\n"
1117
1158
  " if context_directory[action_key] then\n"
@@ -1128,11 +1169,12 @@ static unsigned int loadPeekActionCommand(ruleset *tree, binding *rulesBinding)
1128
1169
  "end\n"
1129
1170
  "if frame then\n"
1130
1171
  " redis.call(\"zadd\", action_key, tonumber(ARGV[1]), new_sid)\n"
1172
+ " local state_version = redis.call(\"hget\", state_key .. \"!v\", new_sid)\n"
1131
1173
  " if #ARGV == 2 then\n"
1132
1174
  " local state = redis.call(\"hget\", state_key, new_sid)\n"
1133
- " return {new_sid, state, cjson.encode({[action_name] = fixup_frame(frame)})}\n"
1175
+ " return {new_sid, tonumber(state_version), state, cjson.encode({[action_name] = fixup_frame(frame)})}\n"
1134
1176
  " else\n"
1135
- " return {new_sid, cjson.encode({[action_name] = fixup_frame(frame)})}\n"
1177
+ " return {new_sid, tonumber(state_version), cjson.encode({[action_name] = fixup_frame(frame)})}\n"
1136
1178
  " end\n"
1137
1179
  "end\n",
1138
1180
  name,
@@ -1168,7 +1210,7 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
1168
1210
  char *lua = NULL;
1169
1211
  char *oldLua;
1170
1212
 
1171
- #ifdef _WIN32
1213
+ #ifdef _WIN32
1172
1214
  char *actionKey = (char *)_alloca(sizeof(char)*(nameLength + 3));
1173
1215
  sprintf_s(actionKey, nameLength + 3, "%s!a", name);
1174
1216
  #else
@@ -1206,6 +1248,7 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
1206
1248
  oldLua = lua;
1207
1249
  if (asprintf(&lua,
1208
1250
  "%stoggle = false\n"
1251
+ "context_directory = {}\n"
1209
1252
  "context = {}\n"
1210
1253
  "reviewers = {}\n"
1211
1254
  "context[\"reviewers\"] = reviewers\n"
@@ -1236,9 +1279,10 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
1236
1279
  for (unsigned int iii = 0; iii < currentJoin->expressionsLength; ++iii) {
1237
1280
  unsigned int expressionOffset = tree->nextPool[currentJoin->expressionsOffset + iii];
1238
1281
  expression *expr = &tree->expressionPool[expressionOffset];
1239
- char *currentAlias = &tree->stringPool[expr->aliasOffset];
1240
1282
  char *currentKey = &tree->stringPool[expr->nameOffset];
1283
+ char *currentAlias = &tree->stringPool[expr->aliasOffset];
1241
1284
  char *nextKeyTest;
1285
+
1242
1286
  if (iii == (currentJoin->expressionsLength - 1)) {
1243
1287
  nextKeyTest = (char*)calloc(1, sizeof(char));
1244
1288
  if (!nextKeyTest) {
@@ -1384,6 +1428,7 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
1384
1428
  char *test = NULL;
1385
1429
  char *primaryKeyLua = NULL;
1386
1430
  char *primaryFrameKeyLua = NULL;
1431
+
1387
1432
  unsigned int result = createTest(tree, expr, &test, &primaryKeyLua, &primaryFrameKeyLua);
1388
1433
  if (result != RULES_OK) {
1389
1434
  return result;
@@ -1569,6 +1614,9 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
1569
1614
  "%sif toggle then\n"
1570
1615
  " context[\"process_key\"] = process_key_with_span\n"
1571
1616
  " context[\"process_key_count\"] = %d\n"
1617
+ " if not process_message(message) then\n"
1618
+ " return\n"
1619
+ " end\n"
1572
1620
  "end\n",
1573
1621
  lua,
1574
1622
  currentNode->value.c.span) == -1) {
@@ -1582,6 +1630,9 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
1582
1630
  "%sif toggle then\n"
1583
1631
  " context[\"process_key\"] = process_key_with_cap\n"
1584
1632
  " context[\"process_key_count\"] = %d\n"
1633
+ " if not process_message(message) then\n"
1634
+ " return\n"
1635
+ " end\n"
1585
1636
  "end\n",
1586
1637
  lua,
1587
1638
  currentNode->value.c.cap) == -1) {
@@ -1595,6 +1646,9 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
1595
1646
  "%sif toggle then\n"
1596
1647
  " context[\"process_key\"] = process_key_with_window\n"
1597
1648
  " context[\"process_key_count\"] = %d\n"
1649
+ " if not process_message(message) then\n"
1650
+ " return\n"
1651
+ " end\n"
1598
1652
  "end\n",
1599
1653
  lua,
1600
1654
  currentNode->value.c.count) == -1) {
@@ -1998,6 +2052,41 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
1998
2052
  " end\n"
1999
2053
  " return queue_lock\n"
2000
2054
  "end\n"
2055
+ "local process_message = function(message)\n"
2056
+ " for index = 6, 5 + keys_count, 1 do\n"
2057
+ " results = {}\n"
2058
+ " unpacked_results = {}\n"
2059
+ " key = ARGV[index]\n"
2060
+ " context = context_directory[key]\n"
2061
+ " if context then\n"
2062
+ " keys = context[\"keys\"]\n"
2063
+ " reviewers = context[\"reviewers\"]\n"
2064
+ " frame_packers = context[\"frame_packers\"]\n"
2065
+ " frame_unpackers = context[\"frame_unpackers\"]\n"
2066
+ " primary_message_keys = context[\"primary_message_keys\"]\n"
2067
+ " primary_frame_keys = context[\"primary_frame_keys\"]\n"
2068
+ " directory = context[\"directory\"]\n"
2069
+ " results_key = context[\"results_key\"]\n"
2070
+ " inverse_directory = context[\"inverse_directory\"]\n"
2071
+ " expressions_count = context[\"expressions_count\"]\n"
2072
+ " local process_key = context[\"process_key\"]\n"
2073
+ " local process_key_count = context[\"process_key_count\"]\n"
2074
+ " queue_action = process_key(message, process_key_count) or queue_action\n"
2075
+ " if assert_fact == 0 and events_message_cache[tostring(message[\"id\"])] == false then\n"
2076
+ " break\n"
2077
+ " end\n"
2078
+ " end\n"
2079
+ " end\n"
2080
+ " if queue_action then\n"
2081
+ " if not redis.call(\"zscore\", actions_key, sid) then\n"
2082
+ " redis.call(\"zadd\", actions_key , score, sid)\n"
2083
+ " end\n"
2084
+ " if assert_fact == 0 then\n"
2085
+ " return false\n"
2086
+ " end\n"
2087
+ " end\n"
2088
+ " return true\n"
2089
+ "end\n"
2001
2090
  "local message = nil\n"
2002
2091
  "if #ARGV > (6 + keys_count) then\n"
2003
2092
  " message = {}\n"
@@ -2012,6 +2101,10 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
2012
2101
  " else\n"
2013
2102
  " message[ARGV[index]] = false\n"
2014
2103
  " end\n"
2104
+ " elseif ARGV[index + 2] == \"5\" then\n"
2105
+ " message[ARGV[index]] = cjson.decode(ARGV[index + 1])\n"
2106
+ " elseif ARGV[index + 2] == \"7\" then\n"
2107
+ " message[ARGV[index]] = \"$null\"\n"
2015
2108
  " end\n"
2016
2109
  " end\n"
2017
2110
  " if assert_fact == 1 then\n"
@@ -2032,33 +2125,7 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
2032
2125
  "for index = 6, 5 + keys_count, 1 do\n"
2033
2126
  " input_keys[ARGV[index]] = true\n"
2034
2127
  "end\n"
2035
- "%sfor index = 6, 5 + keys_count, 1 do\n"
2036
- " results = {}\n"
2037
- " unpacked_results = {}\n"
2038
- " key = ARGV[index]\n"
2039
- " context = context_directory[key]\n"
2040
- " keys = context[\"keys\"]\n"
2041
- " reviewers = context[\"reviewers\"]\n"
2042
- " frame_packers = context[\"frame_packers\"]\n"
2043
- " frame_unpackers = context[\"frame_unpackers\"]\n"
2044
- " primary_message_keys = context[\"primary_message_keys\"]\n"
2045
- " primary_frame_keys = context[\"primary_frame_keys\"]\n"
2046
- " directory = context[\"directory\"]\n"
2047
- " results_key = context[\"results_key\"]\n"
2048
- " inverse_directory = context[\"inverse_directory\"]\n"
2049
- " expressions_count = context[\"expressions_count\"]\n"
2050
- " local process_key = context[\"process_key\"]\n"
2051
- " local process_key_count = context[\"process_key_count\"]\n"
2052
- " queue_action = process_key(message, process_key_count) or queue_action\n"
2053
- " if assert_fact == 0 and events_message_cache[tostring(message[\"id\"])] == false then\n"
2054
- " break\n"
2055
- " end\n"
2056
- "end\n"
2057
- "if queue_action then\n"
2058
- " if not redis.call(\"zscore\", actions_key, sid) then\n"
2059
- " redis.call(\"zadd\", actions_key , score, sid)\n"
2060
- " end\n"
2061
- "end\n",
2128
+ "%s\n",
2062
2129
  name,
2063
2130
  name,
2064
2131
  name,
@@ -2493,22 +2560,40 @@ unsigned int formatStoreSession(void *rulesBinding,
2493
2560
  char *sid,
2494
2561
  char *state,
2495
2562
  unsigned char tryExists,
2496
- char **command) {
2563
+ char **storeCommand,
2564
+ char **versionCommand) {
2497
2565
  binding *currentBinding = (binding*)rulesBinding;
2498
2566
 
2499
2567
  int result;
2500
2568
  if (tryExists) {
2501
- result = redisFormatCommand(command,
2569
+ result = redisFormatCommand(storeCommand,
2502
2570
  "hsetnx %s %s %s",
2503
2571
  currentBinding->sessionHashset,
2504
2572
  sid,
2505
2573
  state);
2574
+ if (result == 0) {
2575
+ return ERR_OUT_OF_MEMORY;
2576
+ }
2577
+
2578
+ result = redisFormatCommand(versionCommand,
2579
+ "hsetnx %s!v %s 0",
2580
+ currentBinding->sessionHashset,
2581
+ sid);
2506
2582
  } else {
2507
- result = redisFormatCommand(command,
2583
+ result = redisFormatCommand(storeCommand,
2508
2584
  "hset %s %s %s",
2509
2585
  currentBinding->sessionHashset,
2510
2586
  sid,
2511
2587
  state);
2588
+
2589
+ if (result == 0) {
2590
+ return ERR_OUT_OF_MEMORY;
2591
+ }
2592
+
2593
+ result = redisFormatCommand(versionCommand,
2594
+ "hincrby %s!v %s 1",
2595
+ currentBinding->sessionHashset,
2596
+ sid);
2512
2597
  }
2513
2598
 
2514
2599
  if (result == 0) {
@@ -3028,6 +3113,38 @@ unsigned int getSession(void *rulesBinding, char *sid, char **state) {
3028
3113
  return REDIS_OK;
3029
3114
  }
3030
3115
 
3116
+ unsigned int getSessionVersion(void *rulesBinding, char *sid, unsigned long *stateVersion) {
3117
+ binding *currentBinding = (binding*)rulesBinding;
3118
+ redisContext *reContext = currentBinding->reContext;
3119
+ unsigned int result = redisAppendCommand(reContext,
3120
+ "hget %s!v %s",
3121
+ currentBinding->sessionHashset,
3122
+ sid);
3123
+ if (result != REDIS_OK) {
3124
+ return ERR_REDIS_ERROR;
3125
+ }
3126
+
3127
+ redisReply *reply;
3128
+ result = tryGetReply(reContext, &reply);
3129
+ if (result != RULES_OK) {
3130
+ return result;
3131
+ }
3132
+
3133
+ if (reply->type == REDIS_REPLY_ERROR) {
3134
+ freeReplyObject(reply);
3135
+ return ERR_REDIS_ERROR;
3136
+ }
3137
+
3138
+ if (reply->type != REDIS_REPLY_INTEGER) {
3139
+ *stateVersion = 0;
3140
+ } else {
3141
+ *stateVersion = reply->integer;
3142
+ }
3143
+
3144
+ freeReplyObject(reply);
3145
+ return REDIS_OK;
3146
+ }
3147
+
3031
3148
  unsigned int deleteSession(void *rulesBinding, char *sid) {
3032
3149
  binding *currentBinding = (binding*)rulesBinding;
3033
3150
  redisContext *reContext = currentBinding->reContext;
data/src/rules/net.h CHANGED
@@ -74,7 +74,8 @@ unsigned int formatStoreSession(void *rulesBinding,
74
74
  char *sid,
75
75
  char *state,
76
76
  unsigned char tryExists,
77
- char **command);
77
+ char **storeCommand,
78
+ char **versionCommand);
78
79
 
79
80
  unsigned int formatStoreSessionFact(void *rulesBinding,
80
81
  char *sid,
@@ -148,6 +149,10 @@ unsigned int getSession(void *rulesBinding,
148
149
  char *sid,
149
150
  char **state);
150
151
 
152
+ unsigned int getSessionVersion(void *rulesBinding,
153
+ char *sid,
154
+ unsigned long *stateVersion);
155
+
151
156
  unsigned int deleteSession(void *rulesBinding,
152
157
  char *sid);
153
158
 
data/src/rules/rules.h CHANGED
@@ -131,7 +131,8 @@ unsigned int startUpdateState(void *handle,
131
131
  void **rulesBinding,
132
132
  unsigned int *replyCount);
133
133
 
134
- unsigned int assertState(void *handle,
134
+ unsigned int assertState(void *handle,
135
+ char *sid,
135
136
  char *state);
136
137
 
137
138
  unsigned int startAction(void *handle,
data/src/rules/state.c CHANGED
@@ -453,6 +453,17 @@ unsigned int getState(void *handle, char *sid, char **state) {
453
453
  return getSession(rulesBinding, sid, state);
454
454
  }
455
455
 
456
+ unsigned int getStateVersion(void *handle, char *sid, unsigned long *stateVersion) {
457
+ void *rulesBinding = NULL;
458
+ unsigned int result = resolveBinding(handle, sid, &rulesBinding);
459
+ if (result != RULES_OK) {
460
+ return result;
461
+ }
462
+
463
+ return getSessionVersion(rulesBinding, sid, stateVersion);
464
+ }
465
+
466
+
456
467
  unsigned int deleteState(void *handle, char *sid) {
457
468
  void *rulesBinding = NULL;
458
469
  unsigned int result = resolveBinding(handle, sid, &rulesBinding);
data/src/rules/state.h CHANGED
@@ -57,3 +57,6 @@ unsigned int fetchStateProperty(void *tree,
57
57
  unsigned char ignoreStaleState,
58
58
  char **state,
59
59
  jsonProperty **property);
60
+ unsigned int getStateVersion(void *handle,
61
+ char *sid,
62
+ unsigned long *stateVersion);
data/src/rulesrb/rules.c CHANGED
@@ -420,11 +420,12 @@ static VALUE rbRetractFacts(VALUE self, VALUE handle, VALUE facts) {
420
420
  return Qnil;
421
421
  }
422
422
 
423
- static VALUE rbAssertState(VALUE self, VALUE handle, VALUE state) {
423
+ static VALUE rbAssertState(VALUE self, VALUE handle, VALUE sid, VALUE state) {
424
424
  Check_Type(handle, T_FIXNUM);
425
+ Check_Type(sid, T_STRING);
425
426
  Check_Type(state, T_STRING);
426
427
 
427
- unsigned int result = assertState((void *)FIX2LONG(handle), RSTRING_PTR(state));
428
+ unsigned int result = assertState((void *)FIX2LONG(handle), RSTRING_PTR(sid), RSTRING_PTR(state));
428
429
  if (result == RULES_OK || result == ERR_EVENT_NOT_HANDLED || result == ERR_EVENT_OBSERVED) {
429
430
  return INT2FIX(result);
430
431
  } else {
@@ -671,7 +672,7 @@ void Init_rules() {
671
672
  rb_define_singleton_method(rulesModule, "queue_retract_fact", rbQueueRetractFact, 4);
672
673
  rb_define_singleton_method(rulesModule, "start_retract_facts", rbStartRetractFacts, 2);
673
674
  rb_define_singleton_method(rulesModule, "retract_facts", rbRetractFacts, 2);
674
- rb_define_singleton_method(rulesModule, "assert_state", rbAssertState, 2);
675
+ rb_define_singleton_method(rulesModule, "assert_state", rbAssertState, 3);
675
676
  rb_define_singleton_method(rulesModule, "start_update_state", rbStartUpdateState, 3);
676
677
  rb_define_singleton_method(rulesModule, "start_action", rbStartAction, 1);
677
678
  rb_define_singleton_method(rulesModule, "complete_action", rbCompleteAction, 3);
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.10
4
+ version: 0.34.11
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-09-06 00:00:00.000000000 Z
11
+ date: 2016-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -129,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
129
  version: '0'
130
130
  requirements: []
131
131
  rubyforge_project:
132
- rubygems_version: 2.0.14
132
+ rubygems_version: 2.0.14.1
133
133
  signing_key:
134
134
  specification_version: 4
135
135
  summary: for real time analytics (a Ruby Rules Engine)