datahike-browser-tests 1.0.0

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 (324) hide show
  1. package/.circleci/config.yml +405 -0
  2. package/.circleci/scripts/gen_ci.clj +194 -0
  3. package/.cirrus.yml +60 -0
  4. package/.clj-kondo/babashka/sci/config.edn +1 -0
  5. package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
  6. package/.clj-kondo/config.edn +95 -0
  7. package/.dir-locals.el +2 -0
  8. package/.github/FUNDING.yml +3 -0
  9. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
  10. package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
  11. package/.github/ISSUE_TEMPLATE/config.yml +6 -0
  12. package/.github/pull_request_template.md +24 -0
  13. package/.github/workflows/native-image.yml +84 -0
  14. package/LICENSE +203 -0
  15. package/README.md +273 -0
  16. package/bb/deps.edn +9 -0
  17. package/bb/resources/github-fingerprints +3 -0
  18. package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
  19. package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
  20. package/bb/resources/native-image-tests/run-native-image-tests +74 -0
  21. package/bb/resources/native-image-tests/run-python-tests +22 -0
  22. package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
  23. package/bb/resources/native-image-tests/testconfig.edn +5 -0
  24. package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  25. package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
  26. package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
  27. package/bb/resources/template/pom.xml +22 -0
  28. package/bb/src/tools/build.clj +132 -0
  29. package/bb/src/tools/clj_kondo.clj +32 -0
  30. package/bb/src/tools/deploy.clj +26 -0
  31. package/bb/src/tools/examples.clj +19 -0
  32. package/bb/src/tools/npm.clj +100 -0
  33. package/bb/src/tools/python.clj +14 -0
  34. package/bb/src/tools/release.clj +94 -0
  35. package/bb/src/tools/test.clj +148 -0
  36. package/bb/src/tools/version.clj +47 -0
  37. package/bb.edn +269 -0
  38. package/benchmark/src/benchmark/cli.clj +195 -0
  39. package/benchmark/src/benchmark/compare.clj +157 -0
  40. package/benchmark/src/benchmark/config.clj +316 -0
  41. package/benchmark/src/benchmark/measure.clj +187 -0
  42. package/benchmark/src/benchmark/store.clj +190 -0
  43. package/benchmark/test/benchmark/measure_test.clj +156 -0
  44. package/build.clj +30 -0
  45. package/config.edn +49 -0
  46. package/deps.edn +138 -0
  47. package/dev/sandbox.clj +82 -0
  48. package/dev/sandbox.cljs +127 -0
  49. package/dev/sandbox_benchmarks.clj +27 -0
  50. package/dev/sandbox_client.clj +87 -0
  51. package/dev/sandbox_transact_bench.clj +109 -0
  52. package/dev/user.clj +79 -0
  53. package/doc/README.md +96 -0
  54. package/doc/adl/README.md +6 -0
  55. package/doc/adl/adr-000-adr.org +28 -0
  56. package/doc/adl/adr-001-attribute-references.org +15 -0
  57. package/doc/adl/adr-002-build-tooling.org +54 -0
  58. package/doc/adl/adr-003-db-meta-data.md +52 -0
  59. package/doc/adl/adr-004-github-flow.md +40 -0
  60. package/doc/adl/adr-XYZ-template.md +30 -0
  61. package/doc/adl/index.org +3 -0
  62. package/doc/assets/datahike-logo.svg +3 -0
  63. package/doc/assets/datahiking-invoice.org +85 -0
  64. package/doc/assets/hhtree2.png +0 -0
  65. package/doc/assets/network_topology.svg +624 -0
  66. package/doc/assets/perf.png +0 -0
  67. package/doc/assets/schema_mindmap.mm +132 -0
  68. package/doc/assets/schema_mindmap.svg +970 -0
  69. package/doc/assets/temporal_index.mm +74 -0
  70. package/doc/backend-development.md +78 -0
  71. package/doc/bb-pod.md +89 -0
  72. package/doc/benchmarking.md +360 -0
  73. package/doc/bindings/edn-conversion.md +383 -0
  74. package/doc/cli.md +162 -0
  75. package/doc/cljdoc.edn +27 -0
  76. package/doc/cljs-support.md +133 -0
  77. package/doc/config.md +406 -0
  78. package/doc/contributing.md +114 -0
  79. package/doc/datalog-vs-sql.md +210 -0
  80. package/doc/datomic_differences.md +109 -0
  81. package/doc/development/pull-api-ns.md +186 -0
  82. package/doc/development/pull-frame-state-diagram.jpg +0 -0
  83. package/doc/distributed.md +566 -0
  84. package/doc/entity_spec.md +92 -0
  85. package/doc/gc.md +273 -0
  86. package/doc/java-api.md +808 -0
  87. package/doc/javascript-api.md +421 -0
  88. package/doc/libdatahike.md +86 -0
  89. package/doc/logging_and_error_handling.md +43 -0
  90. package/doc/norms.md +66 -0
  91. package/doc/schema-migration.md +85 -0
  92. package/doc/schema.md +287 -0
  93. package/doc/storage-backends.md +363 -0
  94. package/doc/store-id-refactoring.md +596 -0
  95. package/doc/time_variance.md +325 -0
  96. package/doc/unstructured.md +167 -0
  97. package/doc/versioning.md +261 -0
  98. package/examples/basic/README.md +19 -0
  99. package/examples/basic/deps.edn +6 -0
  100. package/examples/basic/docker-compose.yml +13 -0
  101. package/examples/basic/src/examples/core.clj +60 -0
  102. package/examples/basic/src/examples/schema.clj +155 -0
  103. package/examples/basic/src/examples/store.clj +60 -0
  104. package/examples/basic/src/examples/time_travel.clj +185 -0
  105. package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
  106. package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  107. package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
  108. package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
  109. package/examples/java/README.md +162 -0
  110. package/examples/java/pom.xml +62 -0
  111. package/examples/java/src/main/java/examples/QuickStart.java +115 -0
  112. package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
  113. package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
  114. package/flake.lock +27 -0
  115. package/flake.nix +27 -0
  116. package/http-server/datahike/http/middleware.clj +75 -0
  117. package/http-server/datahike/http/server.clj +269 -0
  118. package/java/src/datahike/java/Database.java +274 -0
  119. package/java/src/datahike/java/Datahike.java +281 -0
  120. package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
  121. package/java/src/datahike/java/DatahikeTest.java +370 -0
  122. package/java/src/datahike/java/EDN.java +170 -0
  123. package/java/src/datahike/java/IEntity.java +11 -0
  124. package/java/src/datahike/java/Keywords.java +161 -0
  125. package/java/src/datahike/java/SchemaFlexibility.java +52 -0
  126. package/java/src/datahike/java/Util.java +219 -0
  127. package/karma.conf.js +19 -0
  128. package/libdatahike/compile-cpp +7 -0
  129. package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
  130. package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
  131. package/libdatahike/src/test_cpp.cpp +61 -0
  132. package/npm-package/PUBLISHING.md +140 -0
  133. package/npm-package/README.md +226 -0
  134. package/npm-package/package.template.json +34 -0
  135. package/npm-package/test-isomorphic.ts +281 -0
  136. package/npm-package/test.js +557 -0
  137. package/npm-package/typescript-test.ts +70 -0
  138. package/package.json +16 -0
  139. package/pydatahike/README.md +569 -0
  140. package/pydatahike/pyproject.toml +91 -0
  141. package/pydatahike/setup.py +42 -0
  142. package/pydatahike/src/datahike/__init__.py +134 -0
  143. package/pydatahike/src/datahike/_native.py +250 -0
  144. package/pydatahike/src/datahike/_version.py +2 -0
  145. package/pydatahike/src/datahike/database.py +722 -0
  146. package/pydatahike/src/datahike/edn.py +311 -0
  147. package/pydatahike/src/datahike/py.typed +0 -0
  148. package/pydatahike/tests/conftest.py +17 -0
  149. package/pydatahike/tests/test_basic.py +170 -0
  150. package/pydatahike/tests/test_database.py +51 -0
  151. package/pydatahike/tests/test_edn_conversion.py +299 -0
  152. package/pydatahike/tests/test_query.py +99 -0
  153. package/pydatahike/tests/test_schema.py +55 -0
  154. package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
  155. package/resources/example_server.edn +4 -0
  156. package/shadow-cljs.edn +56 -0
  157. package/src/data_readers.clj +7 -0
  158. package/src/datahike/api/impl.cljc +176 -0
  159. package/src/datahike/api/specification.cljc +633 -0
  160. package/src/datahike/api/types.cljc +261 -0
  161. package/src/datahike/api.cljc +41 -0
  162. package/src/datahike/array.cljc +99 -0
  163. package/src/datahike/cli.clj +166 -0
  164. package/src/datahike/cljs.cljs +6 -0
  165. package/src/datahike/codegen/cli.clj +406 -0
  166. package/src/datahike/codegen/clj_kondo.clj +291 -0
  167. package/src/datahike/codegen/java.clj +403 -0
  168. package/src/datahike/codegen/naming.cljc +33 -0
  169. package/src/datahike/codegen/native.clj +559 -0
  170. package/src/datahike/codegen/pod.clj +488 -0
  171. package/src/datahike/codegen/python.clj +838 -0
  172. package/src/datahike/codegen/report.clj +55 -0
  173. package/src/datahike/codegen/typescript.clj +262 -0
  174. package/src/datahike/codegen/validation.clj +145 -0
  175. package/src/datahike/config.cljc +294 -0
  176. package/src/datahike/connections.cljc +16 -0
  177. package/src/datahike/connector.cljc +265 -0
  178. package/src/datahike/constants.cljc +142 -0
  179. package/src/datahike/core.cljc +297 -0
  180. package/src/datahike/datom.cljc +459 -0
  181. package/src/datahike/db/interface.cljc +119 -0
  182. package/src/datahike/db/search.cljc +305 -0
  183. package/src/datahike/db/transaction.cljc +937 -0
  184. package/src/datahike/db/utils.cljc +338 -0
  185. package/src/datahike/db.cljc +956 -0
  186. package/src/datahike/experimental/unstructured.cljc +126 -0
  187. package/src/datahike/experimental/versioning.cljc +172 -0
  188. package/src/datahike/externs.js +31 -0
  189. package/src/datahike/gc.cljc +69 -0
  190. package/src/datahike/http/client.clj +188 -0
  191. package/src/datahike/http/writer.clj +79 -0
  192. package/src/datahike/impl/entity.cljc +218 -0
  193. package/src/datahike/index/interface.cljc +93 -0
  194. package/src/datahike/index/persistent_set.cljc +469 -0
  195. package/src/datahike/index/utils.cljc +44 -0
  196. package/src/datahike/index.cljc +32 -0
  197. package/src/datahike/js/api.cljs +172 -0
  198. package/src/datahike/js/api_macros.clj +22 -0
  199. package/src/datahike/js.cljs +163 -0
  200. package/src/datahike/json.cljc +209 -0
  201. package/src/datahike/lru.cljc +146 -0
  202. package/src/datahike/migrate.clj +39 -0
  203. package/src/datahike/norm/norm.clj +245 -0
  204. package/src/datahike/online_gc.cljc +252 -0
  205. package/src/datahike/pod.clj +155 -0
  206. package/src/datahike/pull_api.cljc +325 -0
  207. package/src/datahike/query.cljc +1945 -0
  208. package/src/datahike/query_stats.cljc +88 -0
  209. package/src/datahike/readers.cljc +62 -0
  210. package/src/datahike/remote.cljc +218 -0
  211. package/src/datahike/schema.cljc +228 -0
  212. package/src/datahike/schema_cache.cljc +42 -0
  213. package/src/datahike/spec.cljc +101 -0
  214. package/src/datahike/store.cljc +80 -0
  215. package/src/datahike/tools.cljc +308 -0
  216. package/src/datahike/transit.cljc +80 -0
  217. package/src/datahike/writer.cljc +239 -0
  218. package/src/datahike/writing.cljc +362 -0
  219. package/src/deps.cljs +1 -0
  220. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
  221. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
  222. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
  223. package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
  224. package/test/datahike/integration_test/config_record_file_test.clj +14 -0
  225. package/test/datahike/integration_test/config_record_test.clj +14 -0
  226. package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
  227. package/test/datahike/integration_test/return_map_test.clj +62 -0
  228. package/test/datahike/integration_test.cljc +67 -0
  229. package/test/datahike/norm/norm_test.clj +124 -0
  230. package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
  231. package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
  232. package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
  233. package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
  234. package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
  235. package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
  236. package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
  237. package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
  238. package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
  239. package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
  240. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
  241. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
  242. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
  243. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
  244. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
  245. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
  246. package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
  247. package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
  248. package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
  249. package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
  250. package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
  251. package/test/datahike/test/api_test.cljc +895 -0
  252. package/test/datahike/test/array_test.cljc +40 -0
  253. package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
  254. package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
  255. package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
  256. package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
  257. package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
  258. package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
  259. package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
  260. package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
  261. package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
  262. package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
  263. package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
  264. package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
  265. package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
  266. package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
  267. package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
  268. package/test/datahike/test/attribute_refs/utils.cljc +128 -0
  269. package/test/datahike/test/cache_test.cljc +38 -0
  270. package/test/datahike/test/components_test.cljc +92 -0
  271. package/test/datahike/test/config_test.cljc +158 -0
  272. package/test/datahike/test/core_test.cljc +105 -0
  273. package/test/datahike/test/datom_test.cljc +44 -0
  274. package/test/datahike/test/db_test.cljc +54 -0
  275. package/test/datahike/test/entity_spec_test.cljc +159 -0
  276. package/test/datahike/test/entity_test.cljc +103 -0
  277. package/test/datahike/test/explode_test.cljc +143 -0
  278. package/test/datahike/test/filter_test.cljc +75 -0
  279. package/test/datahike/test/gc_test.cljc +159 -0
  280. package/test/datahike/test/http/server_test.clj +192 -0
  281. package/test/datahike/test/http/writer_test.clj +86 -0
  282. package/test/datahike/test/ident_test.cljc +32 -0
  283. package/test/datahike/test/index_test.cljc +345 -0
  284. package/test/datahike/test/insert.cljc +125 -0
  285. package/test/datahike/test/java_bindings_test.clj +6 -0
  286. package/test/datahike/test/listen_test.cljc +41 -0
  287. package/test/datahike/test/lookup_refs_test.cljc +266 -0
  288. package/test/datahike/test/lru_test.cljc +27 -0
  289. package/test/datahike/test/migrate_test.clj +297 -0
  290. package/test/datahike/test/model/core.cljc +376 -0
  291. package/test/datahike/test/model/invariant.cljc +142 -0
  292. package/test/datahike/test/model/rng.cljc +82 -0
  293. package/test/datahike/test/model_test.clj +217 -0
  294. package/test/datahike/test/nodejs_test.cljs +262 -0
  295. package/test/datahike/test/online_gc_test.cljc +475 -0
  296. package/test/datahike/test/pod_test.clj +369 -0
  297. package/test/datahike/test/pull_api_test.cljc +474 -0
  298. package/test/datahike/test/purge_test.cljc +144 -0
  299. package/test/datahike/test/query_aggregates_test.cljc +101 -0
  300. package/test/datahike/test/query_find_specs_test.cljc +52 -0
  301. package/test/datahike/test/query_fns_test.cljc +523 -0
  302. package/test/datahike/test/query_interop_test.cljc +47 -0
  303. package/test/datahike/test/query_not_test.cljc +189 -0
  304. package/test/datahike/test/query_or_test.cljc +158 -0
  305. package/test/datahike/test/query_pull_test.cljc +147 -0
  306. package/test/datahike/test/query_rules_test.cljc +248 -0
  307. package/test/datahike/test/query_stats_test.cljc +218 -0
  308. package/test/datahike/test/query_test.cljc +984 -0
  309. package/test/datahike/test/schema_test.cljc +424 -0
  310. package/test/datahike/test/specification_test.cljc +30 -0
  311. package/test/datahike/test/store_test.cljc +78 -0
  312. package/test/datahike/test/stress_test.cljc +57 -0
  313. package/test/datahike/test/time_variance_test.cljc +518 -0
  314. package/test/datahike/test/tools_test.clj +134 -0
  315. package/test/datahike/test/transact_test.cljc +518 -0
  316. package/test/datahike/test/tuples_test.cljc +564 -0
  317. package/test/datahike/test/unstructured_test.cljc +291 -0
  318. package/test/datahike/test/upsert_impl_test.cljc +205 -0
  319. package/test/datahike/test/upsert_test.cljc +363 -0
  320. package/test/datahike/test/utils.cljc +110 -0
  321. package/test/datahike/test/validation_test.cljc +48 -0
  322. package/test/datahike/test/versioning_test.cljc +56 -0
  323. package/test/datahike/test.cljc +66 -0
  324. package/tests.edn +24 -0
@@ -0,0 +1,316 @@
1
+ (ns benchmark.config)
2
+
3
+ (def comparison-context-cell-order [:fn :backend :index :schema :history :db-datoms :tx-datoms :data-type :data-in-db?])
4
+
5
+ (def csv-cols
6
+ [{:name :fn :title "Function" :path [:context :function]}
7
+ {:name :index :title "Index" :path [:context :dh-config :index]}
8
+ {:name :backend :title "Backend" :path [:context :dh-config :backend]}
9
+ {:name :schema :title "Schema" :path [:context :dh-config :schema-flexibility]}
10
+ {:name :history :title "History" :path [:context :dh-config :keep-history?]}
11
+ {:name :db-datoms :title "DB Datoms" :path [:context :db-datoms]}
12
+ {:name :db-entities :title "DB Entities" :path [:context :db-entities]}
13
+ {:name :tx-datoms :title "TX Datoms" :path [:context :execution :tx-datoms]}
14
+ {:name :tx-entities :title "TX Entities" :path [:context :execution :tx-entities]}
15
+ {:name :data-type :title "Data Type" :path [:context :execution :data-type]}
16
+ {:name :data-in-db? :title "Q Data in DB?" :path [:context :execution :data-in-db?]}
17
+ {:name :mean :title "Mean Time" :path [:time :mean]}
18
+ {:name :std :title "Time Std" :path [:time :std]}
19
+ {:name :median :title "Median Time" :path [:time :median]}
20
+ {:name :min :title "Minimum Time" :path [:time :min]}
21
+ {:name :max :title "Maximum Time" :path [:time :max]}
22
+ {:name :count :title "Time Count" :path [:time :count]}
23
+ {:name :tags :title "Tags" :path [:tag]}])
24
+
25
+ (def named-db-configs
26
+ {"mem-set" {:store {:backend :mem :id "performance-set"}
27
+ :index :datahike.index/persistent-set
28
+ :keep-history? false
29
+ :search-cache-size 0
30
+ :store-cache-size 1
31
+ :schema-flexibility :write}
32
+ "mem-hht" {:store {:backend :mem :id "performance-hht"}
33
+ :index :datahike.index/hitchhiker-tree
34
+ :keep-history? false
35
+ :search-cache-size 0
36
+ :store-cache-size 1
37
+ :schema-flexibility :write}
38
+ "file-set" {:store {:backend :file :path "/tmp/performance-set"}
39
+ :index :datahike.index/persistent-set
40
+ :keep-history? false
41
+ :search-cache-size 0
42
+ :store-cache-size 1
43
+ :schema-flexibility :write}
44
+ "file-hht" {:store {:backend :file :path "/tmp/performance-hht"}
45
+ :index :datahike.index/hitchhiker-tree
46
+ :keep-history? false
47
+ :search-cache-size 0
48
+ :store-cache-size 1
49
+ :schema-flexibility :write}})
50
+
51
+ (def schema
52
+ [{:db/ident :s1
53
+ :db/valueType :db.type/string
54
+ :db/cardinality :db.cardinality/one}
55
+ {:db/ident :s2
56
+ :db/valueType :db.type/string
57
+ :db/cardinality :db.cardinality/one}
58
+ {:db/ident :i1
59
+ :db/valueType :db.type/bigint
60
+ :db/cardinality :db.cardinality/one}
61
+ {:db/ident :i2
62
+ :db/valueType :db.type/bigint
63
+ :db/cardinality :db.cardinality/one}])
64
+
65
+ (defn rand-str [max-int]
66
+ (format "%15d" (rand-int max-int)))
67
+
68
+ (defn rand-entity [max-int]
69
+ {:s1 (rand-str max-int)
70
+ :s2 (rand-str max-int)
71
+ :i1 (rand-int max-int)
72
+ :i2 (rand-int max-int)})
73
+
74
+ (defn known [attr entities]
75
+ (mapv attr entities))
76
+
77
+ (def m-known (memoize known))
78
+
79
+ (defn known-set [attr entities]
80
+ (set (m-known attr entities)))
81
+
82
+ (def m-known-set (memoize known-set))
83
+
84
+ (defn rand-val-not-in [datatype val-set]
85
+ (let [rand-gen (if (= datatype :int) rand-int rand-str)]
86
+ (loop [i (rand-gen Integer/MAX_VALUE)]
87
+ (if (contains? val-set i)
88
+ (recur (rand-gen Integer/MAX_VALUE))
89
+ i))))
90
+
91
+ (defn rand-attr-val [datatype attr entities in-set?]
92
+ (if in-set?
93
+ #(rand-nth (m-known attr entities))
94
+ #(rand-val-not-in datatype (m-known-set attr entities))))
95
+
96
+ (defn vec-of [n f]
97
+ (vec (repeatedly n f)))
98
+
99
+ ;;; Queries
100
+
101
+ (defn simple-query [db attr val]
102
+ {:query (conj '[:find ?e :where]
103
+ (conj '[?e] attr val))
104
+ :args [db]})
105
+
106
+ (defn limit-query [db attr]
107
+ {:query (conj '[:find ?e ?v :where] ;; pulls entity-count datoms
108
+ (conj '[?e] attr '?v))
109
+ :offset 0
110
+ :limit 100
111
+ :args [db]})
112
+
113
+ (defn e-join-query [db attr1 attr2] ;; entity-count res lines
114
+ {:query (conj '[:find ?e :where]
115
+ (conj '[?e] attr1 '?v1) ;; pulls entity-count datoms
116
+ (conj '[?e] attr2 '?v2)) ;; pulls entity-count datoms
117
+ :args [db]})
118
+
119
+ (defn a-join-query [db attr] ;; entity-count res lines
120
+ {:query (conj '[:find ?v1 ?v2 :where]
121
+ (conj '[?e1] attr '?v1) ;; pulls entity-count datoms
122
+ (conj '[?e2] attr '?v2)) ;; pulls entity-count datoms
123
+ :args [db]})
124
+
125
+ (defn v-join-query [db attr1 attr2] ;; on average entity-count res lines
126
+ {:query (conj '[:find ?e1 ?e2 :where]
127
+ (conj '[?e1] attr1 '?v) ;; pulls entity-count datoms
128
+ (conj '[?e2] attr2 '?v)) ;; pulls entity-count datoms
129
+ :args [db]})
130
+
131
+ (defn e-join-query-first-fixed [db attr1 val1 attr2]
132
+ {:query (conj '[:find ?v2 :where]
133
+ (conj '[?e] attr1 val1)
134
+ (conj '[?e] attr2 '?v2))
135
+ :args [db]})
136
+
137
+ (defn e-join-query-second-fixed [db attr1 attr2 val2]
138
+ {:query (conj '[:find ?v1 :where]
139
+ (conj '[?e] attr1 '?v1)
140
+ (conj '[?e] attr2 val2))
141
+ :args [db]})
142
+
143
+ (defn scalar-arg-query [db attr val]
144
+ {:query (conj '[:find ?e
145
+ :in $ ?v
146
+ :where]
147
+ (conj '[?e] attr '?v))
148
+ :args [db val]})
149
+
150
+ (defn scalar-arg-query-with-join [db attr val]
151
+ {:query (conj '[:find ?e1 ?e2 ?v2
152
+ :in $ ?v1
153
+ :where]
154
+ (conj '[?e1] attr '?v1)
155
+ (conj '[?e2] attr '?v2))
156
+ :args [db val]})
157
+
158
+ (defn vector-arg-query [db attr vals]
159
+ {:query (conj '[:find ?e
160
+ :in $ [?v ...]
161
+ :where]
162
+ (conj '[?e] attr '?v))
163
+ :args [db vals]})
164
+
165
+ (defn less-than-query [db attr]
166
+ {:query (conj '[:find ?e1 ?e2 :where]
167
+ (conj '[?e1] attr '?v1)
168
+ (conj '[?e2] attr '?v2)
169
+ '[(< ?v1 ?v2)])
170
+ :args [db]})
171
+
172
+ (defn equals-query [db attr]
173
+ {:query (conj '[:find ?e1 ?e2 :where]
174
+ (conj '[?e1] attr '?v1)
175
+ (conj '[?e2] attr '?v2)
176
+ '[(= ?v1 ?v2)])
177
+ :args [db]})
178
+
179
+ (defn less-than-query-1-fixed [db attr comp-val]
180
+ {:query (conj '[:find ?e :where]
181
+ (conj '[?e] attr '?v)
182
+ (conj '[]
183
+ (sequence (conj '[< ?v] comp-val))))
184
+ :args [db]})
185
+
186
+ (defn equals-query-1-fixed [db attr comp-val]
187
+ {:query (conj '[:find ?e :where]
188
+ (conj '[?e] attr '?v)
189
+ (conj '[]
190
+ (sequence (conj '[= ?v] comp-val))))
191
+ :args [db]})
192
+
193
+ (defn non-var-queries [db datatypes max-int]
194
+ (apply concat
195
+ (for [data-type datatypes]
196
+ (let [[attr1 attr2 middle-elem] (if (= data-type :int)
197
+ [:i1 :i2 (int (/ max-int 2.0))]
198
+ [:s1 :s2 (format "%15d" (int (/ max-int 2.0)))])]
199
+
200
+ [{:function :e-join-query
201
+ :query (e-join-query db attr1 attr2)
202
+ :details {:data-type data-type}}
203
+
204
+ {:function :a-join-query
205
+ :query (a-join-query db attr1)
206
+ :details {:data-type data-type}}
207
+
208
+ {:function :v-join-query
209
+ :query (v-join-query db attr1 attr2)
210
+ :details {:data-type data-type}}
211
+
212
+ {:function :equals-query
213
+ :query (equals-query db attr1)
214
+ :details {:data-type data-type}}
215
+
216
+ {:function :less-than-query
217
+ :query (less-than-query db attr1)
218
+ :details {:data-type data-type}}
219
+
220
+ {:function :equals-query-1-fixed
221
+ :query (equals-query-1-fixed db attr1 middle-elem)
222
+ :details {:data-type data-type}}
223
+
224
+ {:function :less-than-query-1-fixed
225
+ :query (less-than-query-1-fixed db attr1 middle-elem)
226
+ :details {:data-type data-type}}
227
+
228
+ {:function :limit-query
229
+ :query (limit-query db attr1)
230
+ :details {:data-type data-type}}]))))
231
+
232
+ (defn var-queries [db entities datatypes data-found-opts]
233
+ (apply concat
234
+ (for [data-type datatypes
235
+ data-in-db? data-found-opts]
236
+
237
+ (let [attr1 (if (= data-type :int) :i1 :s1)
238
+ attr2 (if (= data-type :int) :i2 :s2)
239
+ rand-val1 (rand-attr-val data-type attr1 entities data-in-db?)
240
+ rand-val2 (rand-attr-val data-type attr2 entities data-in-db?)]
241
+
242
+ [{:function :simple-query
243
+ :query (simple-query db attr1 (rand-val1))
244
+ :details {:data-type data-type :data-in-db? data-in-db?}}
245
+
246
+ {:function :e-join-query-first-fixed
247
+ :query (e-join-query-first-fixed db :i1 (rand-val1) :i2)
248
+ :details {:data-type data-type :data-in-db? data-in-db?}}
249
+
250
+ {:function :e-join-query-second-fixed
251
+ :query (e-join-query-second-fixed db :i1 :i2 (rand-val2))
252
+ :details {:data-type data-type :data-in-db? data-in-db?}}
253
+
254
+ {:function :scalar-arg-query
255
+ :query (scalar-arg-query db :i1 (rand-val1))
256
+ :details {:data-type data-type :data-in-db? data-in-db?}}
257
+
258
+ {:function :scalar-arg-query-with-join
259
+ :query (scalar-arg-query-with-join db :i1 (rand-val1))
260
+ :details {:data-type data-type :data-in-db? data-in-db?}}
261
+
262
+ {:function :vector-arg-query
263
+ :query (vector-arg-query db :i1 (vec-of 10 rand-val1))
264
+ :details {:data-type data-type :data-in-db? data-in-db?}}]))))
265
+
266
+ (defn cache-check-queries [db entities datatypes data-found-opts]
267
+ (apply concat
268
+ (for [data-type datatypes
269
+ data-in-db? data-found-opts]
270
+ (let [attr (if (= data-type :int) :i1 :s1)
271
+ rand-val (rand-attr-val data-type attr entities data-in-db?)
272
+ val (rand-val)]
273
+ [{:function :simple-query-first-run
274
+ :query (simple-query db attr val)
275
+ :details {:data-type data-type :data-in-db? data-in-db?}}
276
+ {:function :simple-query-second-run
277
+ :query (simple-query db attr val)
278
+ :details {:data-type data-type :data-in-db? data-in-db?}}]))))
279
+
280
+ (defn aggregate-queries [entities]
281
+ [{:function :sum-query
282
+ :query {:query '[:find (sum ?x)
283
+ :in [?x ...]]
284
+ :args [(repeatedly (count entities) #(rand-int 100))]}
285
+ :details {:data-type :int}}
286
+ {:function :avg-query
287
+ :query {:query '[:find (avg ?x)
288
+ :in [?x ...]]
289
+ :args [(repeatedly (count entities) #(rand-int 100))]}
290
+ :details {:data-type :int}}
291
+ {:function :median-query
292
+ :query {:query '[:find (median ?x)
293
+ :in [?x ...]]
294
+ :args [(repeatedly (count entities) #(rand-int 100))]}
295
+ :details {:data-type :int}}
296
+ {:function :variance-query
297
+ :query {:query '[:find (variance ?x)
298
+ :in [?x ...]]
299
+ :args [(repeatedly (count entities) #(rand-int 100))]}
300
+ :details {:data-type :int}}
301
+ {:function :stddev-query
302
+ :query {:query '[:find (stddev ?x)
303
+ :in [?x ...]]
304
+ :args [(repeatedly (count entities) #(rand-int 100))]}
305
+ :details {:data-type :int}}
306
+ {:function :max-query
307
+ :query {:query '[:find (max ?x)
308
+ :in [?x ...]]
309
+ :args [(repeatedly (count entities) #(rand-int 100))]}
310
+ :details {:data-type :int}}])
311
+
312
+ (defn all-queries [db entities datatypes data-found-opts]
313
+ (concat (non-var-queries db datatypes (count entities))
314
+ (var-queries db entities datatypes data-found-opts)
315
+ (cache-check-queries db entities datatypes data-found-opts)
316
+ (aggregate-queries entities)))
@@ -0,0 +1,187 @@
1
+ (ns benchmark.measure
2
+ (:require [benchmark.config :as c]
3
+ [taoensso.timbre :as log]
4
+ [datahike.api :as d]
5
+ [datahike.store :as ds]
6
+ [datahike.index :as di])
7
+ (:import [java.util UUID]))
8
+
9
+ (defmacro timed
10
+ "Evaluates expr. Returns the value of expr and the time in a map."
11
+ [expr]
12
+ `(let [start# (. System (nanoTime))
13
+ ret# ~expr]
14
+ {:res ret# :t (/ (double (- (. System (nanoTime)) start#)) 1000000.0)}))
15
+
16
+ (defn init-db [config]
17
+ (d/delete-database config)
18
+ (let [config (d/create-database config)]
19
+ [(d/connect config) config]))
20
+
21
+ (defn init-tx [entity-count conn]
22
+ (when (= :write (get-in @conn [:config :schema-flexibility]))
23
+ (d/transact conn c/schema))
24
+ (if (pos? entity-count)
25
+ (vec (for [entities (->> (repeatedly entity-count (partial c/rand-entity entity-count))
26
+ (partition 100000 100000 nil))]
27
+ (d/transact conn (vec entities))))
28
+ []))
29
+
30
+ (defn time-context-map
31
+ ([t config function db-entities db-datoms]
32
+ (time-context-map t config function db-entities db-datoms nil))
33
+ ([t config function db-entities db-datoms exec]
34
+ (cond-> {:time t
35
+ :context {:dh-config config
36
+ :function function
37
+ :db-entities db-entities
38
+ :db-datoms db-datoms}}
39
+ (some? exec) (assoc-in [:context :execution] exec))))
40
+
41
+ (defn measure-connection-time [iterations unique-cfg simple-cfg db-entities db-datoms]
42
+ (->> (range iterations)
43
+ (map #(do (log/debug (str " - iteration no. " % ))
44
+ (let [timed-conn (timed (d/connect unique-cfg))]
45
+ (d/release (:res timed-conn))
46
+ (time-context-map (:t timed-conn) simple-cfg :connection db-entities db-datoms))) )
47
+ doall))
48
+
49
+ (defn measure-query-times
50
+ [{:keys [iterations data-found-opts query data-types]} initial-tx conn config db-entities db-datoms]
51
+ (let [data-found (case data-found-opts
52
+ true [true]
53
+ false [false]
54
+ :all [true false])
55
+ queries (if (pos? (count initial-tx))
56
+ (c/all-queries @conn initial-tx data-types data-found)
57
+ (c/non-var-queries @conn data-types (count initial-tx)))
58
+ filtered-queries (if (= query :all)
59
+ queries
60
+ (filter #(= query (:function %)) queries))]
61
+ (->> filtered-queries
62
+ (mapcat (fn [{:keys [function query details]}]
63
+ (log/info (str " Querying with " function " using " details ))
64
+ (->> (range iterations)
65
+ (map #(do (log/debug (str " - iteration no. " % ))
66
+ (time-context-map (:t (timed (d/q query @conn)))
67
+ config function db-entities db-datoms details)))
68
+ doall)))
69
+ doall)))
70
+
71
+ (defn measure-transaction-times
72
+ [{:keys [iterations tx-entity-counts]} conn config db-entities db-datoms]
73
+ (->> tx-entity-counts
74
+ (mapcat (fn [tx-entities]
75
+ (let [tx-datoms (* (count c/schema) tx-entities)]
76
+ (log/info (str " Transacting " tx-datoms " entities"))
77
+ (->> (range iterations)
78
+ (map #(do (log/debug (str " - iteration no. " % ))
79
+ (let [tx (vec (repeatedly tx-entities (partial c/rand-entity Integer/MAX_VALUE)))
80
+ timed-transact (timed (d/transact conn tx))]
81
+ (d/transact conn (mapv (fn [dat]
82
+ [(if (:keep-history? (:config @conn))
83
+ :db.purge/entity
84
+ :db/retractEntity)
85
+ (.-e dat)])
86
+ (:tx-data (:res timed-transact))))
87
+ (time-context-map (:t timed-transact) config :transaction db-entities db-datoms
88
+ {:tx-entities tx-entities :tx-datoms tx-datoms}))))
89
+ doall))))
90
+ doall))
91
+
92
+ (defn measure-performance-full
93
+ ([entity-count options cfg] (measure-performance-full entity-count options cfg {}))
94
+ ([entity-count {:keys [iterations function] :as options} config
95
+ {:keys [spec-fn-name make-fn-invocation] :as _specified-fn}]
96
+ (let [unique-cfg (assoc config :name (str (UUID/randomUUID)))
97
+ simple-cfg (-> config
98
+ (assoc :backend (get-in config [:store :backend]))
99
+ (dissoc :store))
100
+ datom-count (* entity-count (count c/schema))
101
+ [conn unique-cfg] (init-db unique-cfg)
102
+ initial-tx (init-tx entity-count conn)
103
+ measurements (vec (if (some? make-fn-invocation)
104
+ (do
105
+ (log/info (str " Measuring function '" spec-fn-name "'..."))
106
+ (->> (range iterations)
107
+ (map #(do (log/debug (str " - iteration no. " % ))
108
+ (time-context-map (:t (timed (make-fn-invocation conn))) simple-cfg (keyword spec-fn-name)
109
+ entity-count datom-count)))
110
+ doall))
111
+ (let [query-times
112
+ (when (#{:all :query} function)
113
+ (log/info (str " Measuring query times..." ))
114
+ (measure-query-times options initial-tx conn simple-cfg entity-count datom-count))
115
+ transaction-times
116
+ (when (contains? #{:all :transaction} function)
117
+ (log/info (str " Measuring transaction times..."))
118
+ (measure-transaction-times options conn simple-cfg entity-count datom-count))
119
+ connection-times
120
+ (when (#{:all :connection} function)
121
+ (log/info (str " Measuring connection times..."))
122
+ (d/release conn)
123
+ (measure-connection-time iterations unique-cfg simple-cfg entity-count datom-count))]
124
+ (concat query-times transaction-times connection-times))))]
125
+ (d/delete-database unique-cfg)
126
+ measurements)))
127
+
128
+ (defn time-statistics [times]
129
+ (let [n (count times)
130
+ sorted (sort times)
131
+ mean (/ (apply + times) n)]
132
+ {:mean mean
133
+ :median (nth sorted (int (/ n 2)))
134
+ :std (->> times
135
+ (map #(* (- % mean) (- % mean)))
136
+ (apply +)
137
+ (* (/ 1.0 n))
138
+ Math/sqrt)
139
+ :min (first sorted)
140
+ :max (last sorted)
141
+ :count n
142
+ :observations (vec times)}))
143
+
144
+ (defn requested-configs [{:keys [config-name history backend search-caches store-caches schema index] :as _options}]
145
+ (if config-name
146
+ [(get c/named-db-configs config-name)]
147
+ (vec (for [index-type (if (= :all index)
148
+ (-> (methods di/default-index-config) keys set (disj :default))
149
+ [index])
150
+ backend-type (if (= :all backend)
151
+ (-> (methods ds/default-config) keys set (disj :default))
152
+ [backend])
153
+ keep-history (if (= :all history)
154
+ [true false]
155
+ [history])
156
+ schema-flexibility (if (= :all schema)
157
+ [:read :write]
158
+ [schema])
159
+ search-cache search-caches
160
+ store-cache store-caches]
161
+ {:index index-type
162
+ :store {:backend backend-type}
163
+ :keep-history? keep-history
164
+ :search-cache-size search-cache
165
+ :store-cache-size store-cache
166
+ :schema-flexibility schema-flexibility}))))
167
+
168
+ (defn get-measurements
169
+ ([options] (get-measurements options (requested-configs options) {}))
170
+ ([options configs] (get-measurements options configs {}))
171
+ ([{:keys [db-entity-counts db-samples] :as options} configs specified-fn]
172
+ (->> (for [cfg configs
173
+ entity-count db-entity-counts]
174
+ (let [datom-count (* entity-count (count c/schema))
175
+ simple-cfg (-> cfg
176
+ (assoc :backend (get-in cfg [:store :backend]))
177
+ (update :index name)
178
+ (dissoc :store))]
179
+ (log/info "Get measurements for DB of size" datom-count "and config:" simple-cfg)
180
+ (->> (range db-samples)
181
+ (mapcat #(do (log/debug (str "- db instance no. " % ))
182
+ (measure-performance-full entity-count options cfg specified-fn)))
183
+ doall)))
184
+ (apply concat)
185
+ (group-by :context)
186
+ (map (fn [[context group]]
187
+ {:context context :time (time-statistics (map :time group))})))))
@@ -0,0 +1,190 @@
1
+ (ns benchmark.store
2
+ (:require [clojure.edn :as edn]
3
+ [clj-http.client :as client]
4
+ [clojure.string :refer [join]]
5
+ [clojure.pprint :refer [pprint]]
6
+ [benchmark.config :as c]))
7
+
8
+ ;; Remote server output
9
+
10
+ (defrecord RemoteDB [baseurl token dbname])
11
+
12
+ (def schema
13
+ [{:db/ident :dh-config
14
+ :db/valueType :db.type/ref
15
+ :db/cardinality :db.cardinality/one}
16
+ {:db/ident :dh-config/name
17
+ :db/valueType :db.type/string
18
+ :db/cardinality :db.cardinality/one
19
+ :db/unique :db.unique/identity}
20
+ {:db/ident :dh-config/index
21
+ :db/valueType :db.type/keyword
22
+ :db/cardinality :db.cardinality/one}
23
+ {:db/ident :dh-config/keep-history?
24
+ :db/valueType :db.type/boolean
25
+ :db/cardinality :db.cardinality/one}
26
+ {:db/ident :dh-config/schema-flexibility
27
+ :db/valueType :db.type/keyword
28
+ :db/cardinality :db.cardinality/one}
29
+ {:db/ident :dh-config/backend
30
+ :db/valueType :db.type/keyword
31
+ :db/cardinality :db.cardinality/one}
32
+
33
+ {:db/ident :time
34
+ :db/valueType :db.type/ref
35
+ :db/cardinality :db.cardinality/one
36
+ :db/isComponent true}
37
+ {:db/ident :time/mean
38
+ :db/valueType :db.type/double
39
+ :db/cardinality :db.cardinality/one}
40
+ {:db/ident :time/median
41
+ :db/valueType :db.type/double
42
+ :db/cardinality :db.cardinality/one}
43
+ {:db/ident :time/std
44
+ :db/valueType :db.type/double
45
+ :db/cardinality :db.cardinality/one}
46
+ {:db/ident :time/std
47
+ :db/valueType :db.type/double
48
+ :db/cardinality :db.cardinality/one}
49
+ {:db/ident :time/count
50
+ :db/valueType :db.type/long
51
+ :db/cardinality :db.cardinality/one}
52
+
53
+ {:db/ident :function
54
+ :db/valueType :db.type/keyword
55
+ :db/cardinality :db.cardinality/one}
56
+
57
+ {:db/ident :db-size
58
+ :db/valueType :db.type/long
59
+ :db/cardinality :db.cardinality/one}
60
+
61
+ {:db/ident :execution
62
+ :db/valueType :db.type/ref
63
+ :db/cardinality :db.cardinality/one
64
+ :db/isComponent true}
65
+ {:db/ident :execution/tx-size
66
+ :db/valueType :db.type/long
67
+ :db/cardinality :db.cardinality/one}
68
+ {:db/ident :execution/data-type
69
+ :db/valueType :db.type/keyword
70
+ :db/cardinality :db.cardinality/one}
71
+ {:db/ident :execution/data-in-db?
72
+ :db/valueType :db.type/boolean
73
+ :db/cardinality :db.cardinality/one}
74
+
75
+ {:db/ident :tag ;; for branch identifier
76
+ :db/valueType :db.type/string
77
+ :db/cardinality :db.cardinality/many}])
78
+
79
+
80
+ (defn parse-body [{:keys [body] :as _response}]
81
+ (if-not (empty? body)
82
+ (edn/read-string body)
83
+ ""))
84
+
85
+ (defn db-request
86
+ ([db method route] (db-request db method route nil))
87
+ ([db method route body]
88
+ (-> (client/request (merge {:url (str (:baseurl db) "/" route)
89
+ :method method
90
+ :content-type "application/edn"
91
+ :accept "application/edn"}
92
+ (when (or (= method :post) body)
93
+ {:body (str body)})
94
+ {:headers {:authorization (str "token " (:token db))
95
+ :db-name (:dbname db)}}))
96
+ parse-body)))
97
+
98
+ (defn transact-data [db tx-data]
99
+ (db-request db :post "transact" {:tx-data tx-data}))
100
+
101
+ (defn get-datoms [db]
102
+ (db-request db :post "datoms" {:index :eavt}))
103
+
104
+ (defn get-schema [db]
105
+ (db-request db :get "schema"))
106
+
107
+ (defn transact-results [db results]
108
+ (transact-data db results))
109
+
110
+ (defn transact-missing-schema [db]
111
+ (let [current-schema (get-schema db)
112
+ defined-attribs (vals current-schema)
113
+ missing-schema (filterv (fn [entity] (not-any? #(= % (:db/ident entity))
114
+ defined-attribs))
115
+ schema)]
116
+ (when (not-empty missing-schema)
117
+ (transact-data db missing-schema))))
118
+
119
+ (defn add-ns-to-keys [current-ns hmap]
120
+ (reduce-kv (fn [m k v]
121
+ (let [next-key (if (= current-ns "") k (keyword (str current-ns "/" (name k))))
122
+ next-ns (name k)
123
+ next-val (cond
124
+ (map? v)
125
+ (add-ns-to-keys next-ns v)
126
+
127
+ (and (vector? v) (map? (first v)))
128
+ (mapv (partial add-ns-to-keys next-ns) v)
129
+
130
+ :else v)]
131
+ (assoc m next-key next-val)))
132
+ {}
133
+ hmap))
134
+
135
+ (defn server-description [options]
136
+ (select-keys options [:db-server-url :db-token :db-name]))
137
+
138
+ ;; file output
139
+
140
+ (defn save-measurements-to-file [paths measurements]
141
+ (let [filename (first paths)]
142
+ (try
143
+ (if (pos? (count paths))
144
+ (do (spit filename measurements)
145
+ (println "Measurements successfully saved to" filename))
146
+ (println measurements))
147
+ (catch Exception e
148
+ (println measurements)
149
+ (println (str "Something went wrong while trying to save measurements to file " filename ":"))
150
+ (.printStackTrace e)))))
151
+
152
+ ;; multi method implementations
153
+
154
+ (defmulti save
155
+ (fn [options _paths _measurements] (:output-format options)))
156
+
157
+ (defmethod save :default [_options _paths measurements]
158
+ (println "No output format given!")
159
+ (println "Using standard output channel...")
160
+ (pprint measurements))
161
+
162
+ (defmethod save "edn" [_options paths measurements]
163
+ (save-measurements-to-file paths measurements))
164
+
165
+ (defmethod save "csv" [_options paths measurements]
166
+ (let [col-paths (map :path c/csv-cols)
167
+ titles (map :title c/csv-cols)
168
+ csv (str (join "\t" titles) "\n"
169
+ (join "\n" (for [result (sort-by (apply juxt (map (fn [path] (fn [measurement] (get-in measurement path)))
170
+ col-paths))
171
+ measurements)]
172
+ (join "\t" (map (fn [path] (get-in result path ""))
173
+ col-paths)))))]
174
+ (save-measurements-to-file paths csv)))
175
+
176
+ (defmethod save "remote-db" [options _paths measurements]
177
+ (let [rdb (apply ->RemoteDB (server-description options))
178
+ db-entry (mapv #(->> (dissoc % :context)
179
+ (merge (:context %))
180
+ (add-ns-to-keys ""))
181
+ measurements)]
182
+ (println "Database used:" rdb)
183
+ (try
184
+ (transact-missing-schema rdb)
185
+ (transact-results rdb db-entry)
186
+ (println "Successfully saved measurements to remote database.")
187
+ (catch Exception e
188
+ (println measurements)
189
+ (println (str "Something went wrong while trying to save measurements to remote database:"))
190
+ (.printStackTrace e)))))