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,101 @@
1
+ (ns datahike.spec
2
+ (:require [datahike.connector :refer [connection?]]
3
+ [datahike.datom :refer [datom?]]
4
+ [datahike.db.utils :as dbu]
5
+ [spec-tools.data-spec :as ds]
6
+ [clojure.spec.alpha :as s])
7
+ #?(:clj
8
+ (:import [clojure.lang IAtom]
9
+ [java.util Date])))
10
+
11
+ (defn set-of [pred] (s/every pred :kind set?))
12
+
13
+ (defn date? [d]
14
+ #?(:cljs (instance? js/Date d)
15
+ :clj (instance? Date d)))
16
+
17
+ (def time-point? (s/or :int int? :date date?))
18
+
19
+ (def SDB dbu/db?)
20
+
21
+ (def SConfig (s/alt :config :datahike/config
22
+ :deprecated/map :deprecated/config
23
+ :deprecated/uri string?))
24
+
25
+ (def SConnection connection?)
26
+
27
+ (def SEId (s/or :number number? :coll sequential? :keyword keyword?))
28
+
29
+ (def SPullOptions
30
+ (ds/spec
31
+ {:name ::pull-options
32
+ :keys-default ds/req
33
+ :spec {:selector coll? ;; TODO: spec more of selector
34
+ :eid SEId}}))
35
+
36
+ (def SDatom datom?)
37
+
38
+ (def SDatoms
39
+ (s/coll-of SDatom))
40
+
41
+ (def STxMeta (s/nilable coll?))
42
+
43
+ (def STransactionReport
44
+ (ds/spec
45
+ {:name ::transaction-report
46
+ :keys-default ds/req
47
+ :spec {:db-before SDB
48
+ :db-after SDB
49
+ :tx-data SDatoms
50
+ :tempids map?
51
+ :tx-meta STxMeta}}))
52
+
53
+ (def SQueryArgs
54
+ (ds/spec
55
+ {:name ::query-args
56
+ :keys-default ds/req
57
+ :spec {:query (s/or :vec vector? :map map? :str string?)
58
+ :args (s/coll-of (set-of vector?))
59
+ (ds/opt :limit) int?
60
+ (ds/opt :offset) int?}}))
61
+
62
+ (def STransactions
63
+ (s/coll-of (s/or :seq coll? :map map? :nil nil?)))
64
+
65
+ (def SWithArgs
66
+ (ds/spec
67
+ {:name ::with-args
68
+ :keys-default ds/opt
69
+ :spec {:tx-data STransactions
70
+ :tx-meta STxMeta}}))
71
+
72
+ (def SIndexRangeArgs
73
+ (ds/spec
74
+ {:name ::index-range-args
75
+ :keys-default ds/req
76
+ :spec {:attrid keyword?
77
+ :start any?
78
+ :end any?}}))
79
+
80
+ (def SIndexLookupArgs
81
+ (ds/spec
82
+ {:name ::index-lookup-args
83
+ :keys-default ds/req
84
+ :spec {:index keyword?
85
+ (ds/opt :components) (s/nilable coll?)}}))
86
+
87
+ (def SSchemaEntry :datahike.schema/schema)
88
+
89
+ (def SSchema
90
+ (s/map-of any? SSchemaEntry))
91
+
92
+ (def SMetrics
93
+ (ds/spec
94
+ {:name ::metrics
95
+ :keys-default ds/req
96
+ :spec {:count int?
97
+ :avet-count int?
98
+ :per-attr-counts map?
99
+ :per-entity-counts map?
100
+ (ds/opt :temporal-count) int?
101
+ (ds/opt :temporal-avet-count) int?}}))
@@ -0,0 +1,80 @@
1
+ (ns ^:no-doc datahike.store
2
+ "Datahike-specific store utilities.
3
+
4
+ Most store lifecycle operations (create, connect, delete, release) are now
5
+ handled by konserve.store directly. This namespace provides:
6
+
7
+ - add-cache-and-handlers: Wraps konserve stores with LRU cache and BTSet handlers
8
+ - store-identity: Returns store UUID from config
9
+ - ready-store: Tiered-specific initialization (populate cache from backend)"
10
+ (:require [konserve.tiered :as kt]
11
+ [datahike.index :as di]
12
+ [konserve.cache :as kc]
13
+ #?(:clj [clojure.core.cache :as cache]
14
+ :cljs [cljs.cache :as cache])
15
+ [konserve.utils :refer [#?(:clj async+sync) *default-sync-translation*]
16
+ #?@(:cljs [:refer-macros [async+sync]])]
17
+ [superv.async #?(:clj :refer :cljs :refer-macros) [go-try- <?-]]
18
+ #?(:cljs [clojure.core.async :refer-macros [go]])))
19
+
20
+ ;; =============================================================================
21
+ ;; Cache and Handlers
22
+ ;; =============================================================================
23
+
24
+ (defn add-cache-and-handlers
25
+ "Wrap a raw konserve store with LRU cache and Datahike BTSet handlers.
26
+
27
+ The cache improves read performance by keeping frequently accessed keys
28
+ in memory. The handlers enable persistent-sorted-set serialization."
29
+ [raw-store config]
30
+ (di/add-konserve-handlers
31
+ config
32
+ (kc/ensure-cache
33
+ raw-store
34
+ (atom (cache/lru-cache-factory {} :threshold (:store-cache-size config))))))
35
+
36
+ ;; =============================================================================
37
+ ;; Store Identity
38
+ ;; =============================================================================
39
+
40
+ (defn store-identity
41
+ "Returns the UUID that identifies the store.
42
+
43
+ All konserve stores require an :id field containing a UUID.
44
+ This is the stable identifier used for connection tracking,
45
+ distributed coordination, and store matching."
46
+ [config]
47
+ (:id config))
48
+
49
+ ;; =============================================================================
50
+ ;; Ready Store (Tiered-Specific)
51
+ ;; =============================================================================
52
+
53
+ (defmulti ready-store
54
+ "Notify when the store is ready to use.
55
+
56
+ Most backends are ready immediately after connection. The :tiered backend
57
+ needs special handling to populate the memory frontend from the backend
58
+ before use."
59
+ {:arglists '([config store])}
60
+ (fn [{:keys [backend]} _store]
61
+ backend))
62
+
63
+ (defmethod ready-store :default [{:keys [opts]} _]
64
+ (async+sync (:sync? opts) *default-sync-translation*
65
+ (go-try- true)))
66
+
67
+ (defmethod ready-store :tiered [{:keys [opts frontend-config backend-config]} store]
68
+ "Populate tiered store frontend from backend and sync on connect.
69
+
70
+ This ensures:
71
+ 1. Memory frontend has cached data for immediate queries
72
+ 2. Subsequent sync handshakes send accurate timestamps (only fetch newer keys)"
73
+ (async+sync (:sync? (or opts {:sync? true})) *default-sync-translation*
74
+ (go-try-
75
+ ;; Config uses :frontend-config/:backend-config (avoids collision with :backend :tiered)
76
+ ;; Store record uses :frontend-store/:backend-store (field names in TieredStore)
77
+ (<?- (ready-store (assoc frontend-config :opts opts) (:frontend-store store)))
78
+ (<?- (ready-store (assoc backend-config :opts opts) (:backend-store store)))
79
+ (<?- (kt/sync-on-connect store kt/populate-missing-strategy opts))
80
+ true)))
@@ -0,0 +1,308 @@
1
+ (ns ^:no-doc datahike.tools
2
+ (:require
3
+ [superv.async :refer [throw-if-exception-]]
4
+ [clojure.core.async.impl.protocols :as async-impl]
5
+ [hasch.core :refer [uuid]]
6
+ [clojure.core.async :as async]
7
+ #?(:clj [clojure.java.io :as io])
8
+ [taoensso.timbre :as log])
9
+ #?(:cljs (:require-macros [datahike.tools :refer [raise]]))
10
+ #?(:clj (:import [java.util Properties UUID Date]
11
+ [java.util.concurrent CompletableFuture]
12
+ [java.net InetAddress])))
13
+
14
+ (defn combine-hashes [x y]
15
+ #?(:clj (clojure.lang.Util/hashCombine x y)
16
+ :cljs (hash-combine x y)))
17
+
18
+ (defn -match-vector-class [x]
19
+ (case x
20
+ _ :negative
21
+ * :any
22
+ :positive))
23
+
24
+ (defn -match-vector [path pattern-pos pattern-size pattern-symbols pairs]
25
+ (cond
26
+ (< pattern-pos pattern-size)
27
+ (let [groups (group-by (comp -match-vector-class #(nth % pattern-pos) first) pairs)
28
+ sub (fn [p pairs] (-match-vector (conj path p)
29
+ (inc pattern-pos)
30
+ pattern-size
31
+ pattern-symbols
32
+ pairs))]
33
+ (if (= [:any] (keys groups))
34
+ (sub '* (:any groups))
35
+ `(if ~(nth pattern-symbols pattern-pos)
36
+ ~(sub 1 (mapcat groups [:positive :any]))
37
+ ~(sub '_ (mapcat groups [:negative :any])))))
38
+
39
+ (not= 1 (count pairs)) (throw (ex-info "There should be exactly one expression at leaf"
40
+ {:path path}))
41
+ :else (-> pairs first second)))
42
+
43
+ (defmacro match-vector [input-vector & pattern-expr-pairs]
44
+ {:pre [(sequential? pattern-expr-pairs)
45
+ (even? (count pattern-expr-pairs))]}
46
+ (let [pairs (partition 2 pattern-expr-pairs)
47
+ patterns (map first pairs)
48
+ _ (assert (every? sequential? patterns))
49
+ pattern-sizes (into #{} (map count) patterns)
50
+ _ (assert (= 1 (count pattern-sizes)))
51
+ pattern-size (first pattern-sizes)
52
+ symbols (repeatedly pattern-size gensym)]
53
+ `(let [[~@symbols] ~input-vector]
54
+ ~(-match-vector [] 0 pattern-size symbols pairs))))
55
+
56
+ (defn ^:dynamic get-date []
57
+ #?(:clj (Date.)
58
+ :cljs (js/Date.)))
59
+
60
+ (defn ^:dynamic get-time-ms []
61
+ #?(:clj (.getTime (Date.))
62
+ :cljs (.getTime (js/Date.))))
63
+
64
+ (defmacro raise
65
+ "Logging an error and throwing an exception with message and structured data.
66
+ Arguments:
67
+ - Any number of strings that describe the error
68
+ - Last argument is a map of data that helps understanding the source of the error"
69
+ [& fragments]
70
+ (let [msgs (butlast fragments)
71
+ data (last fragments)]
72
+ (list `(log/log! :error :p ~fragments ~{:?line (:line (meta &form))})
73
+ `(throw (ex-info (str ~@(map (fn [m#] (if (string? m#) m# (list 'pr-str m#))) msgs)) ~data)))))
74
+
75
+ ;; adapted from https://clojure.atlassian.net/browse/CLJ-2766
76
+ #?(:clj
77
+ (defn throwable-promise
78
+ "Returns a promise object that can be read with deref/@, and set, once only, with deliver. Calls to deref/@ prior to delivery will block, unless the variant of deref with timeout is used. All subsequent derefs will return the same delivered value without blocking. Exceptions delivered to the promise will throw on deref.
79
+
80
+ Also supports core.async take! to optionally consume values without blocking the reader thread."
81
+ []
82
+ (let [cf (CompletableFuture.)
83
+ p (async/promise-chan)]
84
+ (reify
85
+ clojure.lang.IDeref
86
+ (deref [_] (throw-if-exception- (try (.get cf) (catch Throwable t t))))
87
+ clojure.lang.IBlockingDeref
88
+ (deref [_ timeout-ms timeout-val]
89
+ (if-let [v (try (.get cf timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) (catch Throwable t t))]
90
+ (throw-if-exception- v)
91
+ timeout-val))
92
+ clojure.lang.IPending
93
+ (isRealized [_] (.isDone cf))
94
+ clojure.lang.IFn
95
+ (invoke [this x]
96
+ (if (instance? Throwable x)
97
+ (.completeExceptionally cf x)
98
+ (.complete cf x))
99
+ (if-not (nil? x) (async/put! p x) (async/close! p))
100
+ this)
101
+ async-impl/ReadPort
102
+ (take! [_this handler] (async-impl/take! p handler))
103
+ async-impl/WritePort
104
+ (put! [_ val handler]
105
+ (if (instance? Throwable val)
106
+ (.completeExceptionally cf val)
107
+ (.complete cf val))
108
+ (async-impl/put! p val handler)))))
109
+ :cljs (def throwable-promise async/promise-chan))
110
+
111
+ #?(:clj
112
+ (defn get-version
113
+ "Retrieves the current version of a dependency. Thanks to https://stackoverflow.com/a/33070806/10978897"
114
+ [dep]
115
+ (let [path (str "META-INF/maven/" (or (namespace dep) (name dep))
116
+ "/" (name dep) "/pom.properties")
117
+ props (io/resource path)]
118
+ (when props
119
+ (with-open [stream (io/input-stream props)]
120
+ (let [props (doto (Properties.) (.load stream))]
121
+ (.getProperty props "version")))))))
122
+
123
+ #?(:clj (def datahike-version (or (get-version 'org.replikativ/datahike) "DEVELOPMENT")))
124
+
125
+ #?(:clj (def hitchhiker-tree-version
126
+ (try (get-version 'io.replikativ/hitchhiker-tree)
127
+ (catch Exception _ nil))))
128
+
129
+ #?(:clj (def persistent-set-version (get-version 'org.replikativ/persistent-sorted-set)))
130
+
131
+ #?(:clj (def konserve-version (get-version 'org.replikativ/konserve)))
132
+
133
+ #?(:clj
134
+ (defmacro meta-data []
135
+ `{:datahike/version ~datahike-version
136
+ :konserve/version ~konserve-version
137
+ :hitchhiker.tree/version ~hitchhiker-tree-version
138
+ :persistent.set/version ~persistent-set-version
139
+ :datahike/id (uuid)
140
+ :datahike/created-at (get-date)}))
141
+
142
+ (defn deep-merge
143
+ "Recursively merges maps together. If all the maps supplied have nested maps
144
+ under the same keys, these nested maps are merged. Otherwise the value is
145
+ overwritten, as in `clojure.core/merge`.
146
+
147
+ Copied from weavejester/medley 1.3.0"
148
+ {:arglists '([& maps])
149
+ :added "1.1.0"}
150
+ ([])
151
+ ([a] a)
152
+ ([a b]
153
+ (when (or a b)
154
+ (letfn [(merge-entry [m e]
155
+ (let [k (key e)
156
+ v' (val e)]
157
+ (if (contains? m k)
158
+ (assoc m k (let [v (get m k)]
159
+ (if (and (map? v) (map? v'))
160
+ (deep-merge v v')
161
+ v')))
162
+ (assoc m k v'))))]
163
+ (reduce merge-entry (or a {}) (seq b)))))
164
+ ([a b & more]
165
+ (reduce deep-merge (or a {}) (cons b more))))
166
+
167
+ (defn timed [f]
168
+ (let [now #?(:clj #(. System (nanoTime))
169
+ :cljs #(* 1000 (. (js/Date.) (getTime))))
170
+ start (now)
171
+ result (f)
172
+ end (now)
173
+ t (/ (double (- end start))
174
+ 1000000.0)]
175
+ {:res result
176
+ :t t}))
177
+
178
+ (defn get-hostname []
179
+ #?(:clj (.getHostAddress (InetAddress/getLocalHost))
180
+ :cljs "" #_(raise "Not supported." {:type :hostname-not-supported})))
181
+
182
+ (defmacro with-destructured-vector [v & var-expr-pairs]
183
+ {:pre [(even? (count var-expr-pairs))]}
184
+ (let [pairs (partition 2 var-expr-pairs)
185
+ vars (mapv first pairs)
186
+ vsym (gensym)
187
+ nsym (gensym)
188
+ generate (fn generate [acc pairs]
189
+ (let [i (count acc)]
190
+ `(if (<= ~nsym ~i)
191
+ ~acc
192
+ ~(if (empty? pairs)
193
+ `(throw (ex-info "Pattern mismatch"
194
+ {:input ~vsym
195
+ :pattern (quote ~var-expr-pairs)}))
196
+ (let [[[_ expr] & pairs] pairs
197
+ g (gensym)]
198
+ `(let [~g ~expr]
199
+ ~(generate (conj acc g) pairs)))))))]
200
+ `(let [~vsym ~v
201
+ ~nsym (count ~vsym)
202
+ ~vars ~vsym]
203
+ ~(generate [] pairs))))
204
+
205
+ (defn- reduce-clauses
206
+ [resolver context clauses]
207
+ (loop [context context
208
+ clauses clauses
209
+ failed-clauses []]
210
+ (if (empty? clauses)
211
+ [context failed-clauses]
212
+ (let [[clause & clauses] clauses]
213
+ (if-let [next-context (resolver context clause)]
214
+ (recur next-context clauses failed-clauses)
215
+ (recur context clauses (conj failed-clauses clause)))))))
216
+
217
+ (defn resolve-clauses [resolver context clauses]
218
+ (if (empty? clauses)
219
+ context
220
+ (let [[context failed-clauses] (reduce-clauses resolver
221
+ context
222
+ clauses)]
223
+ (if (= (count failed-clauses)
224
+ (count clauses))
225
+ (raise "Cannot resolve any more clauses"
226
+ {:clauses clauses})
227
+ (recur resolver context failed-clauses)))))
228
+
229
+ (defn group-by-step
230
+ "Create a step function to use with `transduce` for grouping values"
231
+ [f]
232
+ (fn
233
+ ([] (transient {}))
234
+ ([dst] (persistent! dst))
235
+ ([dst x]
236
+ (let [k (f x)]
237
+ (assoc! dst k (conj (get dst k []) x))))))
238
+
239
+ (defn range-subset-tree
240
+ "This function generates code for a decision tree that for an input expression `input` that has to represent a sequence of growing integers that is a subset of the integers in the sequence `(range length-length)`. Every leaf in the decision tree corresponds to one of the 2^range-length possible subsequences and the `branch-visitor-fn` is called at every leaf with the first argument being the subsequence and the second argument being a mask."
241
+ ([range-length input branch-visitor-fn]
242
+ (if (symbol? input)
243
+ (range-subset-tree range-length
244
+ input
245
+ branch-visitor-fn
246
+ 0
247
+ []
248
+ (vec (repeat range-length nil)))
249
+ (let [sym (gensym)]
250
+ `(let [~sym ~input]
251
+ ~(range-subset-tree range-length sym branch-visitor-fn)))))
252
+ ([range-length input-symbol branch-visitor-fn at acc-inds mask]
253
+ {:pre [(number? range-length)
254
+ (symbol? input-symbol)
255
+ (ifn? branch-visitor-fn)
256
+ (number? at)
257
+ (vector? acc-inds)]}
258
+ (if (= range-length at)
259
+ (branch-visitor-fn acc-inds mask)
260
+ `(if (empty? ~input-symbol)
261
+ ~(branch-visitor-fn acc-inds mask)
262
+ (if (= ~at (first ~input-symbol))
263
+ (let [~input-symbol (rest ~input-symbol)]
264
+ ~(range-subset-tree range-length
265
+ input-symbol
266
+ branch-visitor-fn
267
+ (inc at)
268
+ (conj acc-inds at)
269
+ (assoc mask at (count acc-inds))))
270
+ ~(range-subset-tree range-length
271
+ input-symbol
272
+ branch-visitor-fn
273
+ (inc at)
274
+ acc-inds
275
+ mask))))))
276
+
277
+ (defn distinct-sorted-seq? [cmp s]
278
+ (if (empty? s)
279
+ true
280
+ (loop [previous (first s)
281
+ s (rest s)]
282
+ (if (empty? s)
283
+ true
284
+ (let [x (first s)]
285
+ (if (neg? (cmp previous x))
286
+ (recur x (rest s))
287
+ false))))))
288
+
289
+ (defn merge-distinct-sorted-seqs
290
+ "Takes a comparator function `cmp` and two sequences `seq-a` and `seq-b` that are both distinct and sorted by `cmp`. Then combines the elements from both sequences to form a new sorted sequence that is distinct. The function distinct-sorted-seq? must return true for all input sequences and the result will also be a sequence for which this function returns true."
291
+ [cmp seq-a seq-b]
292
+ (cond
293
+ (empty? seq-a) seq-b
294
+ (empty? seq-b) seq-a
295
+ :else
296
+ (let [a (first seq-a)
297
+ b (first seq-b)
298
+ i (cmp a b)]
299
+ (cond
300
+ (< i 0) (cons
301
+ a (lazy-seq
302
+ (merge-distinct-sorted-seqs cmp (rest seq-a) seq-b)))
303
+ (= i 0) (cons
304
+ a (lazy-seq
305
+ (merge-distinct-sorted-seqs cmp (rest seq-a) (rest seq-b))))
306
+ :else (cons
307
+ b (lazy-seq
308
+ (merge-distinct-sorted-seqs cmp seq-a (rest seq-b))))))))
@@ -0,0 +1,80 @@
1
+ (ns datahike.transit
2
+ "Transit related translations."
3
+ (:require [datahike.store :refer [store-identity]]
4
+ [datahike.readers :as readers]
5
+ [datahike.connector]
6
+ [datahike.datom :as dd]
7
+ [cognitect.transit :as transit])
8
+ #?(:clj
9
+ (:import [datahike.datom Datom]
10
+ [datahike.impl.entity Entity]
11
+ [datahike.db HistoricalDB AsOfDB SinceDB])))
12
+
13
+ (def read-handlers
14
+ {"datahike/Connection"
15
+ (transit/read-handler datahike.readers/connection-from-reader)
16
+ "datahike/Datom"
17
+ (transit/read-handler datahike.readers/datom-from-reader)
18
+ "datahike/DB"
19
+ (transit/read-handler datahike.readers/db-from-reader)
20
+ "datahike/HistoricalDB"
21
+ (transit/read-handler datahike.readers/history-from-reader)
22
+ "datahike/SinceDB"
23
+ (transit/read-handler datahike.readers/since-from-reader)
24
+ "datahike/AsOfDB"
25
+ (transit/read-handler datahike.readers/as-of-from-reader)
26
+ "datahike/Entity"
27
+ (transit/read-handler datahike.readers/entity-from-reader)
28
+ "datahike/TxReport"
29
+ (transit/read-handler datahike.db/map->TxReport)})
30
+
31
+ (defn config->store-id [config]
32
+ [(store-identity (:store config))
33
+ (:branch config)])
34
+
35
+ (defn db->map [db]
36
+ (let [{:keys [config meta max-eid max-tx]} db]
37
+ {:store-id (config->store-id config)
38
+ :commit-id (:datahike/commit-id meta)
39
+ :max-eid max-eid
40
+ :max-tx max-tx}))
41
+
42
+ (def write-handlers
43
+ {datahike.connector.Connection
44
+ (transit/write-handler "datahike/Connection"
45
+ #(config->store-id (:config @(:wrapped-atom %))))
46
+
47
+ datahike.datom.Datom
48
+ (transit/write-handler "datahike/Datom"
49
+ (fn [^Datom d]
50
+ [(.-e d) (.-a d) (.-v d) (dd/datom-tx d) (dd/datom-added d)]))
51
+
52
+ datahike.db.TxReport
53
+ (transit/write-handler "datahike/TxReport" #(into {} %))
54
+
55
+ datahike.db.DB
56
+ (transit/write-handler "datahike/DB" db->map)
57
+
58
+ datahike.db.HistoricalDB
59
+ (transit/write-handler "datahike/HistoricalDB"
60
+ (fn [{:keys [origin-db]}]
61
+ {:origin origin-db}))
62
+
63
+ datahike.db.SinceDB
64
+ (transit/write-handler "datahike/SinceDB"
65
+ (fn [{:keys [origin-db time-point]}]
66
+ {:origin origin-db
67
+ :time-point time-point}))
68
+
69
+ datahike.db.AsOfDB
70
+ (transit/write-handler "datahike/AsOfDB"
71
+ (fn [{:keys [origin-db time-point]}]
72
+ {:origin origin-db
73
+ :time-point time-point}))
74
+
75
+ datahike.impl.entity.Entity
76
+ (transit/write-handler "datahike/Entity"
77
+ (fn [^Entity e]
78
+ (assoc (into {} e)
79
+ :db (.-db e)
80
+ :eid (.-eid e))))})