test_redis.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. from contextlib import contextmanager
  2. from datetime import datetime, timedelta, timezone
  3. import pytest
  4. from sentry.testutils.cases import TestCase
  5. from sentry.testutils.helpers.options import override_options
  6. from sentry.tsdb.base import ONE_DAY, ONE_HOUR, ONE_MINUTE, TSDBModel
  7. from sentry.tsdb.redis import CountMinScript, RedisTSDB, SuppressionWrapper
  8. from sentry.utils.dates import to_datetime
  9. def test_suppression_wrapper():
  10. @contextmanager
  11. def raise_after():
  12. yield
  13. raise Exception("Boom!")
  14. with pytest.raises(Exception):
  15. with raise_after():
  16. pass
  17. with SuppressionWrapper(raise_after()):
  18. pass
  19. with SuppressionWrapper(raise_after()):
  20. raise Exception("should not propagate")
  21. class RedisTSDBTest(TestCase):
  22. @override_options(
  23. {"redis.clusters": {"tsdb": {"hosts": {i - 6: {"db": i} for i in range(6, 9)}}}}
  24. )
  25. def setUp(self):
  26. self.db = RedisTSDB(
  27. rollups=(
  28. # time in seconds, samples to keep
  29. (10, 30), # 5 minutes at 10 seconds
  30. (ONE_MINUTE, 120), # 2 hours at 1 minute
  31. (ONE_HOUR, 24), # 1 days at 1 hour
  32. (ONE_DAY, 30), # 30 days at 1 day
  33. ),
  34. vnodes=64,
  35. enable_frequency_sketches=True,
  36. cluster="tsdb",
  37. )
  38. # the point of this test is to demonstrate behaviour with a multi-host cluster
  39. assert len(self.db.cluster.hosts) == 3
  40. def tearDown(self):
  41. with self.db.cluster.all() as client:
  42. client.flushdb()
  43. def test_make_counter_key(self):
  44. result = self.db.make_counter_key(TSDBModel.project, 1, to_datetime(1368889980), 1, None)
  45. assert result == ("ts:1:1368889980:1", 1)
  46. result = self.db.make_counter_key(
  47. TSDBModel.project, 1, to_datetime(1368889980), "foo", None
  48. )
  49. assert result == ("ts:1:1368889980:46", self.db.get_model_key("foo"))
  50. result = self.db.make_counter_key(TSDBModel.project, 1, to_datetime(1368889980), 1, 1)
  51. assert result == ("ts:1:1368889980:1", "1?e=1")
  52. result = self.db.make_counter_key(TSDBModel.project, 1, to_datetime(1368889980), "foo", 1)
  53. assert result == ("ts:1:1368889980:46", str(self.db.get_model_key("foo")) + "?e=1")
  54. def test_get_model_key(self):
  55. result = self.db.get_model_key(1)
  56. assert result == 1
  57. result = self.db.get_model_key("foo")
  58. assert result == "bf4e529197e56a48ae2737505b9736e4"
  59. result = self.db.get_model_key("我爱啤酒")
  60. assert result == "26f980fbe1e8a9d3a0123d2049f95f28"
  61. def test_simple(self):
  62. now = datetime.now(timezone.utc) - timedelta(hours=4)
  63. dts = [now + timedelta(hours=i) for i in range(4)]
  64. def timestamp(d):
  65. t = int(d.timestamp())
  66. return t - (t % 3600)
  67. self.db.incr(TSDBModel.project, 1, dts[0])
  68. self.db.incr(TSDBModel.project, 1, dts[1], count=2)
  69. self.db.incr(TSDBModel.project, 1, dts[1], environment_id=1)
  70. self.db.incr(TSDBModel.project, 1, dts[2])
  71. self.db.incr_multi(
  72. [(TSDBModel.project, 1), (TSDBModel.project, 2)], dts[3], count=3, environment_id=1
  73. )
  74. self.db.incr_multi(
  75. [(TSDBModel.project, 1), (TSDBModel.project, 2)], dts[3], count=1, environment_id=2
  76. )
  77. results = self.db.get_range(TSDBModel.project, [1], dts[0], dts[-1])
  78. assert results == {
  79. 1: [
  80. (timestamp(dts[0]), 1),
  81. (timestamp(dts[1]), 3),
  82. (timestamp(dts[2]), 1),
  83. (timestamp(dts[3]), 4),
  84. ]
  85. }
  86. results = self.db.get_range(TSDBModel.project, [2], dts[0], dts[-1])
  87. assert results == {
  88. 2: [
  89. (timestamp(dts[0]), 0),
  90. (timestamp(dts[1]), 0),
  91. (timestamp(dts[2]), 0),
  92. (timestamp(dts[3]), 4),
  93. ]
  94. }
  95. results = self.db.get_range(TSDBModel.project, [1, 2], dts[0], dts[-1], environment_ids=[1])
  96. assert results == {
  97. 1: [
  98. (timestamp(dts[0]), 0),
  99. (timestamp(dts[1]), 1),
  100. (timestamp(dts[2]), 0),
  101. (timestamp(dts[3]), 3),
  102. ],
  103. 2: [
  104. (timestamp(dts[0]), 0),
  105. (timestamp(dts[1]), 0),
  106. (timestamp(dts[2]), 0),
  107. (timestamp(dts[3]), 3),
  108. ],
  109. }
  110. sum_results = self.db.get_sums(TSDBModel.project, [1, 2], dts[0], dts[-1])
  111. assert sum_results == {1: 9, 2: 4}
  112. sum_results = self.db.get_sums(TSDBModel.project, [1, 2], dts[0], dts[-1], environment_id=1)
  113. assert sum_results == {1: 4, 2: 3}
  114. sum_results = self.db.get_sums(TSDBModel.project, [1, 2], dts[0], dts[-1], environment_id=0)
  115. assert sum_results == {1: 0, 2: 0}
  116. self.db.merge(TSDBModel.project, 1, [2], now, environment_ids=[0, 1, 2])
  117. results = self.db.get_range(TSDBModel.project, [1], dts[0], dts[-1])
  118. assert results == {
  119. 1: [
  120. (timestamp(dts[0]), 1),
  121. (timestamp(dts[1]), 3),
  122. (timestamp(dts[2]), 1),
  123. (timestamp(dts[3]), 8),
  124. ]
  125. }
  126. results = self.db.get_range(TSDBModel.project, [2], dts[0], dts[-1])
  127. assert results == {
  128. 2: [
  129. (timestamp(dts[0]), 0),
  130. (timestamp(dts[1]), 0),
  131. (timestamp(dts[2]), 0),
  132. (timestamp(dts[3]), 0),
  133. ]
  134. }
  135. results = self.db.get_range(TSDBModel.project, [1, 2], dts[0], dts[-1], environment_ids=[1])
  136. assert results == {
  137. 1: [
  138. (timestamp(dts[0]), 0),
  139. (timestamp(dts[1]), 1),
  140. (timestamp(dts[2]), 0),
  141. (timestamp(dts[3]), 6),
  142. ],
  143. 2: [(timestamp(dts[i]), 0) for i in range(0, 4)],
  144. }
  145. sum_results = self.db.get_sums(TSDBModel.project, [1, 2], dts[0], dts[-1])
  146. assert sum_results == {1: 13, 2: 0}
  147. self.db.delete([TSDBModel.project], [1, 2], dts[0], dts[-1], environment_ids=[0, 1, 2])
  148. sum_results = self.db.get_sums(TSDBModel.project, [1, 2], dts[0], dts[-1])
  149. assert sum_results == {1: 0, 2: 0}
  150. sum_results = self.db.get_sums(TSDBModel.project, [1, 2], dts[0], dts[-1], environment_id=1)
  151. assert sum_results == {1: 0, 2: 0}
  152. def test_count_distinct(self):
  153. now = datetime.now(timezone.utc) - timedelta(hours=4)
  154. dts = [now + timedelta(hours=i) for i in range(4)]
  155. model = TSDBModel.users_affected_by_group
  156. def timestamp(d):
  157. t = int(d.timestamp())
  158. return t - (t % 3600)
  159. self.db.record(model, 1, ("foo", "bar"), dts[0])
  160. self.db.record(model, 1, ("baz",), dts[1], environment_id=1)
  161. self.db.record_multi(((model, 1, ("foo", "bar")), (model, 2, ("bar",))), dts[2])
  162. self.db.record(model, 1, ("baz",), dts[2], environment_id=1)
  163. self.db.record(model, 2, ("foo",), dts[3])
  164. assert self.db.get_distinct_counts_series(model, [1], dts[0], dts[-1], rollup=3600) == {
  165. 1: [
  166. (timestamp(dts[0]), 2),
  167. (timestamp(dts[1]), 1),
  168. (timestamp(dts[2]), 3),
  169. (timestamp(dts[3]), 0),
  170. ]
  171. }
  172. assert self.db.get_distinct_counts_series(model, [2], dts[0], dts[-1], rollup=3600) == {
  173. 2: [
  174. (timestamp(dts[0]), 0),
  175. (timestamp(dts[1]), 0),
  176. (timestamp(dts[2]), 1),
  177. (timestamp(dts[3]), 1),
  178. ]
  179. }
  180. assert self.db.get_distinct_counts_series(
  181. model, [1, 2], dts[0], dts[-1], rollup=3600, environment_id=1
  182. ) == {
  183. 1: [
  184. (timestamp(dts[0]), 0),
  185. (timestamp(dts[1]), 1),
  186. (timestamp(dts[2]), 1),
  187. (timestamp(dts[3]), 0),
  188. ],
  189. 2: [
  190. (timestamp(dts[0]), 0),
  191. (timestamp(dts[1]), 0),
  192. (timestamp(dts[2]), 0),
  193. (timestamp(dts[3]), 0),
  194. ],
  195. }
  196. results = self.db.get_distinct_counts_totals(model, [1, 2], dts[0], dts[-1], rollup=3600)
  197. assert results == {1: 3, 2: 2}
  198. results = self.db.get_distinct_counts_totals(
  199. model, [1, 2], dts[0], dts[-1], rollup=3600, environment_id=1
  200. )
  201. assert results == {1: 1, 2: 0}
  202. results = self.db.get_distinct_counts_totals(
  203. model, [1, 2], dts[0], dts[-1], rollup=3600, environment_id=0
  204. )
  205. assert results == {1: 0, 2: 0}
  206. assert self.db.get_distinct_counts_union(model, [], dts[0], dts[-1], rollup=3600) == 0
  207. assert self.db.get_distinct_counts_union(model, [1, 2], dts[0], dts[-1], rollup=3600) == 3
  208. assert (
  209. self.db.get_distinct_counts_union(
  210. model, [1, 2], dts[0], dts[-1], rollup=3600, environment_id=1
  211. )
  212. == 1
  213. )
  214. assert (
  215. self.db.get_distinct_counts_union(
  216. model, [1, 2], dts[0], dts[-1], rollup=3600, environment_id=0
  217. )
  218. == 0
  219. )
  220. self.db.merge_distinct_counts(model, 1, [2], dts[0], environment_ids=[0, 1])
  221. assert self.db.get_distinct_counts_series(model, [1], dts[0], dts[-1], rollup=3600) == {
  222. 1: [
  223. (timestamp(dts[0]), 2),
  224. (timestamp(dts[1]), 1),
  225. (timestamp(dts[2]), 3),
  226. (timestamp(dts[3]), 1),
  227. ]
  228. }
  229. assert self.db.get_distinct_counts_series(model, [2], dts[0], dts[-1], rollup=3600) == {
  230. 2: [
  231. (timestamp(dts[0]), 0),
  232. (timestamp(dts[1]), 0),
  233. (timestamp(dts[2]), 0),
  234. (timestamp(dts[3]), 0),
  235. ]
  236. }
  237. assert self.db.get_distinct_counts_series(
  238. model, [1, 2], dts[0], dts[-1], rollup=3600, environment_id=1
  239. ) == {
  240. 1: [
  241. (timestamp(dts[0]), 0),
  242. (timestamp(dts[1]), 1),
  243. (timestamp(dts[2]), 1),
  244. (timestamp(dts[3]), 0),
  245. ],
  246. 2: [
  247. (timestamp(dts[0]), 0),
  248. (timestamp(dts[1]), 0),
  249. (timestamp(dts[2]), 0),
  250. (timestamp(dts[3]), 0),
  251. ],
  252. }
  253. results = self.db.get_distinct_counts_totals(model, [1, 2], dts[0], dts[-1], rollup=3600)
  254. assert results == {1: 3, 2: 0}
  255. assert self.db.get_distinct_counts_union(model, [], dts[0], dts[-1], rollup=3600) == 0
  256. assert self.db.get_distinct_counts_union(model, [1], dts[0], dts[-1], rollup=3600) == 3
  257. assert self.db.get_distinct_counts_union(model, [1, 2], dts[0], dts[-1], rollup=3600) == 3
  258. assert self.db.get_distinct_counts_union(model, [2], dts[0], dts[-1], rollup=3600) == 0
  259. self.db.delete_distinct_counts([model], [1, 2], dts[0], dts[-1], environment_ids=[0, 1])
  260. results = self.db.get_distinct_counts_totals(model, [1, 2], dts[0], dts[-1])
  261. assert results == {1: 0, 2: 0}
  262. results = self.db.get_distinct_counts_totals(
  263. model, [1, 2], dts[0], dts[-1], environment_id=1
  264. )
  265. assert results == {1: 0, 2: 0}
  266. def test_frequency_tables(self):
  267. now = datetime.now(timezone.utc)
  268. model = TSDBModel.frequent_issues_by_project
  269. # None of the registered frequency tables actually support
  270. # environments, so we have to pretend like one actually does
  271. self.db.models_with_environment_support = self.db.models_with_environment_support | {model}
  272. rollup = 3600
  273. self.db.record_frequency_multi(
  274. ((model, {"organization:1": {"project:1": 1, "project:2": 2, "project:3": 3}}),), now
  275. )
  276. self.db.record_frequency_multi(
  277. (
  278. (
  279. model,
  280. {
  281. "organization:1": {
  282. "project:1": 1,
  283. "project:2": 1,
  284. "project:3": 1,
  285. "project:4": 1,
  286. },
  287. "organization:2": {"project:5": 1},
  288. },
  289. ),
  290. ),
  291. now - timedelta(hours=1),
  292. )
  293. self.db.record_frequency_multi(
  294. (
  295. (
  296. model,
  297. {
  298. "organization:1": {"project:2": 1, "project:3": 2, "project:4": 3},
  299. "organization:2": {"project:5": 0.5},
  300. },
  301. ),
  302. ),
  303. now - timedelta(hours=1),
  304. environment_id=1,
  305. )
  306. assert self.db.get_most_frequent(
  307. model, ("organization:1", "organization:2"), now, rollup=rollup
  308. ) == {
  309. "organization:1": [("project:3", 3.0), ("project:2", 2.0), ("project:1", 1.0)],
  310. "organization:2": [],
  311. }
  312. assert self.db.get_most_frequent(
  313. model,
  314. ("organization:1", "organization:2"),
  315. now - timedelta(hours=1),
  316. now,
  317. rollup=rollup,
  318. environment_id=1,
  319. ) == {
  320. "organization:1": [("project:4", 3.0), ("project:3", 2.0), ("project:2", 1.0)],
  321. "organization:2": [("project:5", 0.5)],
  322. }
  323. assert self.db.get_most_frequent(
  324. model, ("organization:1", "organization:2"), now, limit=1, rollup=rollup
  325. ) == {"organization:1": [("project:3", 3.0)], "organization:2": []}
  326. assert self.db.get_most_frequent(
  327. model,
  328. ("organization:1", "organization:2"),
  329. now - timedelta(hours=1),
  330. now,
  331. rollup=rollup,
  332. ) == {
  333. "organization:1": [
  334. ("project:3", 3.0 + 3.0),
  335. ("project:2", 2.0 + 2.0),
  336. ("project:4", 4.0),
  337. ("project:1", 1.0 + 1.0),
  338. ],
  339. "organization:2": [("project:5", 1.5)],
  340. }
  341. assert self.db.get_most_frequent(
  342. model,
  343. ("organization:1", "organization:2"),
  344. now - timedelta(hours=1),
  345. now,
  346. rollup=rollup,
  347. environment_id=0,
  348. ) == {"organization:1": [], "organization:2": []}
  349. timestamp = int(now.timestamp() // rollup) * rollup
  350. assert self.db.get_most_frequent_series(
  351. model,
  352. ("organization:1", "organization:2", "organization:3"),
  353. now - timedelta(hours=1),
  354. now,
  355. rollup=rollup,
  356. ) == {
  357. "organization:1": [
  358. (
  359. timestamp - rollup,
  360. {"project:1": 1.0, "project:2": 2.0, "project:3": 3.0, "project:4": 4.0},
  361. ),
  362. (timestamp, {"project:1": 1.0, "project:2": 2.0, "project:3": 3.0}),
  363. ],
  364. "organization:2": [(timestamp - rollup, {"project:5": 1.5}), (timestamp, {})],
  365. "organization:3": [(timestamp - rollup, {}), (timestamp, {})],
  366. }
  367. assert self.db.get_frequency_series(
  368. model,
  369. {
  370. "organization:1": ("project:1", "project:2", "project:3", "project:4"),
  371. "organization:2": ("project:5",),
  372. },
  373. now - timedelta(hours=1),
  374. now,
  375. rollup=rollup,
  376. ) == {
  377. "organization:1": [
  378. (
  379. timestamp - rollup,
  380. {"project:1": 1.0, "project:2": 2.0, "project:3": 3.0, "project:4": 4.0},
  381. ),
  382. (
  383. timestamp,
  384. {"project:1": 1.0, "project:2": 2.0, "project:3": 3.0, "project:4": 0.0},
  385. ),
  386. ],
  387. "organization:2": [
  388. (timestamp - rollup, {"project:5": 1.5}),
  389. (timestamp, {"project:5": 0.0}),
  390. ],
  391. }
  392. assert self.db.get_frequency_series(
  393. model,
  394. {
  395. "organization:1": ("project:1", "project:2", "project:3", "project:4"),
  396. "organization:2": ("project:5",),
  397. },
  398. now - timedelta(hours=1),
  399. now,
  400. rollup=rollup,
  401. environment_id=1,
  402. ) == {
  403. "organization:1": [
  404. (
  405. timestamp - rollup,
  406. {"project:1": 0.0, "project:2": 1.0, "project:3": 2.0, "project:4": 3.0},
  407. ),
  408. (
  409. timestamp,
  410. {"project:1": 0.0, "project:2": 0.0, "project:3": 0.0, "project:4": 0.0},
  411. ),
  412. ],
  413. "organization:2": [
  414. (timestamp - rollup, {"project:5": 0.5}),
  415. (timestamp, {"project:5": 0.0}),
  416. ],
  417. }
  418. assert self.db.get_frequency_totals(
  419. model,
  420. {
  421. "organization:1": ("project:1", "project:2", "project:3", "project:4", "project:5"),
  422. "organization:2": ("project:1", "project:2", "project:3", "project:4", "project:5"),
  423. },
  424. now - timedelta(hours=1),
  425. now,
  426. rollup=rollup,
  427. ) == {
  428. "organization:1": {
  429. "project:1": 1.0 + 1.0,
  430. "project:2": 2.0 + 2.0,
  431. "project:3": 3.0 + 3.0,
  432. "project:4": 4.0,
  433. "project:5": 0.0,
  434. },
  435. "organization:2": {
  436. "project:1": 0.0,
  437. "project:2": 0.0,
  438. "project:3": 0.0,
  439. "project:4": 0.0,
  440. "project:5": 1.5,
  441. },
  442. }
  443. self.db.merge_frequencies(
  444. model, "organization:1", ["organization:2"], now, environment_ids=[0, 1]
  445. )
  446. assert self.db.get_frequency_totals(
  447. model,
  448. {
  449. "organization:1": ("project:1", "project:2", "project:3", "project:4", "project:5"),
  450. "organization:2": ("project:1", "project:2", "project:3", "project:4", "project:5"),
  451. },
  452. now - timedelta(hours=1),
  453. now,
  454. rollup=rollup,
  455. ) == {
  456. "organization:1": {
  457. "project:1": 1.0 + 1.0,
  458. "project:2": 2.0 + 2.0,
  459. "project:3": 3.0 + 3.0,
  460. "project:4": 4.0,
  461. "project:5": 1.5,
  462. },
  463. "organization:2": {
  464. "project:1": 0.0,
  465. "project:2": 0.0,
  466. "project:3": 0.0,
  467. "project:4": 0.0,
  468. "project:5": 0.0,
  469. },
  470. }
  471. assert self.db.get_frequency_totals(
  472. model,
  473. {
  474. "organization:1": ("project:1", "project:2", "project:3", "project:4", "project:5"),
  475. "organization:2": ("project:1", "project:2", "project:3", "project:4", "project:5"),
  476. },
  477. now - timedelta(hours=1),
  478. now,
  479. rollup=rollup,
  480. environment_id=1,
  481. ) == {
  482. "organization:1": {
  483. "project:1": 0.0,
  484. "project:2": 1.0,
  485. "project:3": 2.0,
  486. "project:4": 3.0,
  487. "project:5": 0.5,
  488. },
  489. "organization:2": {
  490. "project:1": 0.0,
  491. "project:2": 0.0,
  492. "project:3": 0.0,
  493. "project:4": 0.0,
  494. "project:5": 0.0,
  495. },
  496. }
  497. self.db.delete_frequencies(
  498. [model],
  499. ["organization:1", "organization:2"],
  500. now - timedelta(hours=1),
  501. now,
  502. environment_ids=[0, 1],
  503. )
  504. assert self.db.get_most_frequent(model, ("organization:1", "organization:2"), now) == {
  505. "organization:1": [],
  506. "organization:2": [],
  507. }
  508. assert self.db.get_most_frequent(
  509. model, ("organization:1", "organization:2"), now, environment_id=1
  510. ) == {"organization:1": [], "organization:2": []}
  511. def test_frequency_table_import_export_no_estimators(self):
  512. client = self.db.cluster.get_local_client_for_key("key")
  513. parameters = [64, 5, 10]
  514. CountMinScript(
  515. ["1:i", "1:e"], ["INCR"] + parameters + [1, "foo", 2, "bar", 3, "baz"], client=client
  516. )
  517. CountMinScript(
  518. ["2:i", "2:e"],
  519. ["INCR"]
  520. + parameters
  521. + [
  522. 1,
  523. "alpha",
  524. 2,
  525. "beta",
  526. 3,
  527. "gamma",
  528. 4,
  529. "delta",
  530. 5,
  531. "epsilon",
  532. 6,
  533. "zeta",
  534. 7,
  535. "eta",
  536. 8,
  537. "theta",
  538. 9,
  539. "iota",
  540. ],
  541. client=client,
  542. )
  543. assert client.exists("1:i")
  544. assert not client.exists("1:e")
  545. assert client.exists("2:i")
  546. assert not client.exists("2:e")
  547. exports = CountMinScript(["2:i", "2:e"], ["EXPORT"] + parameters, client=client)
  548. assert len(exports) == 1
  549. CountMinScript(["1:i", "1:e"], ["IMPORT"] + parameters + [exports[0]], client=client)
  550. assert client.exists("1:i")
  551. assert client.exists("1:e")
  552. def test_frequency_table_import_export_both_estimators(self):
  553. client = self.db.cluster.get_local_client_for_key("key")
  554. parameters = [64, 5, 5]
  555. CountMinScript(
  556. ["1:i", "1:e"],
  557. ["INCR"]
  558. + parameters
  559. + [1, "foo", 2, "bar", 3, "baz", 4, "wilco", 5, "tango", 6, "foxtrot"],
  560. client=client,
  561. )
  562. CountMinScript(
  563. ["2:i", "2:e"],
  564. ["INCR"]
  565. + parameters
  566. + [
  567. 1,
  568. "alpha",
  569. 2,
  570. "beta",
  571. 3,
  572. "gamma",
  573. 4,
  574. "delta",
  575. 5,
  576. "epsilon",
  577. 6,
  578. "zeta",
  579. 7,
  580. "eta",
  581. 8,
  582. "theta",
  583. 9,
  584. "iota",
  585. ],
  586. client=client,
  587. )
  588. assert client.exists("1:i")
  589. assert client.exists("1:e")
  590. assert client.exists("2:i")
  591. assert client.exists("2:e")
  592. exports = CountMinScript(["2:i", "2:e"], ["EXPORT"] + parameters, client=client)
  593. assert len(exports) == 1
  594. CountMinScript(["1:i", "1:e"], ["IMPORT"] + parameters + [exports[0]], client=client)
  595. assert client.exists("1:i")
  596. assert client.exists("1:e")
  597. assert CountMinScript(["1:i", "1:e"], ["RANKED"] + parameters, client=client) == [
  598. [b"iota", b"9"],
  599. [b"theta", b"8"],
  600. [b"eta", b"7"],
  601. [b"zeta", b"6"],
  602. [b"foxtrot", b"6"],
  603. ]
  604. def test_frequency_table_import_export_source_estimators(self):
  605. client = self.db.cluster.get_local_client_for_key("key")
  606. parameters = [64, 5, 5]
  607. CountMinScript(
  608. ["1:i", "1:e"], ["INCR"] + parameters + [5, "foo", 7, "bar", 9, "baz"], client=client
  609. )
  610. CountMinScript(
  611. ["2:i", "2:e"],
  612. ["INCR"]
  613. + parameters
  614. + [
  615. 1,
  616. "alpha",
  617. 2,
  618. "beta",
  619. 3,
  620. "gamma",
  621. 4,
  622. "delta",
  623. 5,
  624. "epsilon",
  625. 6,
  626. "zeta",
  627. 7,
  628. "eta",
  629. 8,
  630. "theta",
  631. 9,
  632. "iota",
  633. ],
  634. client=client,
  635. )
  636. assert client.exists("1:i")
  637. assert not client.exists("1:e")
  638. assert client.exists("2:i")
  639. assert client.exists("2:e")
  640. exports = CountMinScript(["2:i", "2:e"], ["EXPORT"] + parameters, client=client)
  641. assert len(exports) == 1
  642. CountMinScript(["1:i", "1:e"], ["IMPORT"] + parameters + [exports[0]], client=client)
  643. assert client.exists("1:i")
  644. assert client.exists("1:e")
  645. assert CountMinScript(["1:i", "1:e"], ["RANKED"] + parameters, client=client) == [
  646. [b"iota", b"9"],
  647. [b"baz", b"9"],
  648. [b"theta", b"8"],
  649. [b"eta", b"7"],
  650. [b"bar", b"7"],
  651. ]
  652. def test_frequency_table_import_export_destination_estimators(self):
  653. client = self.db.cluster.get_local_client_for_key("key")
  654. parameters = [64, 5, 5]
  655. CountMinScript(
  656. ["1:i", "1:e"],
  657. ["INCR"]
  658. + parameters
  659. + [
  660. 1,
  661. "alpha",
  662. 2,
  663. "beta",
  664. 3,
  665. "gamma",
  666. 4,
  667. "delta",
  668. 5,
  669. "epsilon",
  670. 6,
  671. "zeta",
  672. 7,
  673. "eta",
  674. 8,
  675. "theta",
  676. 9,
  677. "iota",
  678. ],
  679. client=client,
  680. )
  681. CountMinScript(
  682. ["2:i", "2:e"], ["INCR"] + parameters + [5, "foo", 7, "bar", 9, "baz"], client=client
  683. )
  684. assert client.exists("1:i")
  685. assert client.exists("1:e")
  686. assert client.exists("2:i")
  687. assert not client.exists("2:e")
  688. exports = CountMinScript(["2:i", "2:e"], ["EXPORT"] + parameters, client=client)
  689. assert len(exports) == 1
  690. CountMinScript(["1:i", "1:e"], ["IMPORT"] + parameters + [exports[0]], client=client)
  691. assert client.exists("1:i")
  692. assert client.exists("1:e")
  693. assert CountMinScript(["1:i", "1:e"], ["RANKED"] + parameters, client=client) == [
  694. [b"iota", b"9"],
  695. [b"baz", b"9"],
  696. [b"theta", b"8"],
  697. [b"eta", b"7"],
  698. [b"bar", b"7"],
  699. ]