tigerbeetle 0.0.34 → 0.0.37

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/ext/tb_client/extconf.rb +13 -13
  4. data/ext/tb_client/tigerbeetle/LICENSE +177 -0
  5. data/ext/tb_client/tigerbeetle/build.zig +2327 -0
  6. data/ext/tb_client/tigerbeetle/src/aof.zig +1000 -0
  7. data/ext/tb_client/tigerbeetle/src/build_multiversion.zig +808 -0
  8. data/ext/tb_client/tigerbeetle/src/cdc/amqp/protocol.zig +1283 -0
  9. data/ext/tb_client/tigerbeetle/src/cdc/amqp/spec.zig +1704 -0
  10. data/ext/tb_client/tigerbeetle/src/cdc/amqp/types.zig +341 -0
  11. data/ext/tb_client/tigerbeetle/src/cdc/amqp.zig +1450 -0
  12. data/ext/tb_client/tigerbeetle/src/cdc/runner.zig +1659 -0
  13. data/ext/tb_client/tigerbeetle/src/clients/c/samples/main.c +406 -0
  14. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/context.zig +1084 -0
  15. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/echo_client.zig +286 -0
  16. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/packet.zig +158 -0
  17. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal.zig +229 -0
  18. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal_fuzz.zig +110 -0
  19. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.h +386 -0
  20. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.zig +34 -0
  21. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_exports.zig +281 -0
  22. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header.zig +312 -0
  23. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header_test.zig +138 -0
  24. data/ext/tb_client/tigerbeetle/src/clients/c/test.zig +466 -0
  25. data/ext/tb_client/tigerbeetle/src/clients/docs_samples.zig +157 -0
  26. data/ext/tb_client/tigerbeetle/src/clients/docs_types.zig +90 -0
  27. data/ext/tb_client/tigerbeetle/src/clients/dotnet/ci.zig +203 -0
  28. data/ext/tb_client/tigerbeetle/src/clients/dotnet/docs.zig +79 -0
  29. data/ext/tb_client/tigerbeetle/src/clients/dotnet/dotnet_bindings.zig +542 -0
  30. data/ext/tb_client/tigerbeetle/src/clients/go/ci.zig +109 -0
  31. data/ext/tb_client/tigerbeetle/src/clients/go/docs.zig +86 -0
  32. data/ext/tb_client/tigerbeetle/src/clients/go/go_bindings.zig +370 -0
  33. data/ext/tb_client/tigerbeetle/src/clients/go/pkg/native/tb_client.h +386 -0
  34. data/ext/tb_client/tigerbeetle/src/clients/java/ci.zig +167 -0
  35. data/ext/tb_client/tigerbeetle/src/clients/java/docs.zig +126 -0
  36. data/ext/tb_client/tigerbeetle/src/clients/java/java_bindings.zig +996 -0
  37. data/ext/tb_client/tigerbeetle/src/clients/java/src/client.zig +748 -0
  38. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni.zig +3238 -0
  39. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_tests.zig +1718 -0
  40. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_thread_cleaner.zig +190 -0
  41. data/ext/tb_client/tigerbeetle/src/clients/node/ci.zig +104 -0
  42. data/ext/tb_client/tigerbeetle/src/clients/node/docs.zig +75 -0
  43. data/ext/tb_client/tigerbeetle/src/clients/node/node.zig +522 -0
  44. data/ext/tb_client/tigerbeetle/src/clients/node/node_bindings.zig +267 -0
  45. data/ext/tb_client/tigerbeetle/src/clients/node/src/c.zig +3 -0
  46. data/ext/tb_client/tigerbeetle/src/clients/node/src/translate.zig +379 -0
  47. data/ext/tb_client/tigerbeetle/src/clients/python/ci.zig +131 -0
  48. data/ext/tb_client/tigerbeetle/src/clients/python/docs.zig +63 -0
  49. data/ext/tb_client/tigerbeetle/src/clients/python/python_bindings.zig +588 -0
  50. data/ext/tb_client/tigerbeetle/src/clients/rust/assets/tb_client.h +386 -0
  51. data/ext/tb_client/tigerbeetle/src/clients/rust/ci.zig +73 -0
  52. data/ext/tb_client/tigerbeetle/src/clients/rust/docs.zig +106 -0
  53. data/ext/tb_client/tigerbeetle/src/clients/rust/rust_bindings.zig +305 -0
  54. data/ext/tb_client/tigerbeetle/src/config.zig +296 -0
  55. data/ext/tb_client/tigerbeetle/src/constants.zig +790 -0
  56. data/ext/tb_client/tigerbeetle/src/copyhound.zig +202 -0
  57. data/ext/tb_client/tigerbeetle/src/counting_allocator.zig +72 -0
  58. data/ext/tb_client/tigerbeetle/src/direction.zig +11 -0
  59. data/ext/tb_client/tigerbeetle/src/docs_website/build.zig +158 -0
  60. data/ext/tb_client/tigerbeetle/src/docs_website/src/content.zig +156 -0
  61. data/ext/tb_client/tigerbeetle/src/docs_website/src/docs.zig +252 -0
  62. data/ext/tb_client/tigerbeetle/src/docs_website/src/file_checker.zig +313 -0
  63. data/ext/tb_client/tigerbeetle/src/docs_website/src/html.zig +87 -0
  64. data/ext/tb_client/tigerbeetle/src/docs_website/src/page_writer.zig +63 -0
  65. data/ext/tb_client/tigerbeetle/src/docs_website/src/redirects.zig +47 -0
  66. data/ext/tb_client/tigerbeetle/src/docs_website/src/search_index_writer.zig +28 -0
  67. data/ext/tb_client/tigerbeetle/src/docs_website/src/service_worker_writer.zig +61 -0
  68. data/ext/tb_client/tigerbeetle/src/docs_website/src/single_page_writer.zig +169 -0
  69. data/ext/tb_client/tigerbeetle/src/docs_website/src/website.zig +46 -0
  70. data/ext/tb_client/tigerbeetle/src/ewah.zig +445 -0
  71. data/ext/tb_client/tigerbeetle/src/ewah_benchmark.zig +128 -0
  72. data/ext/tb_client/tigerbeetle/src/ewah_fuzz.zig +171 -0
  73. data/ext/tb_client/tigerbeetle/src/fuzz_tests.zig +179 -0
  74. data/ext/tb_client/tigerbeetle/src/integration_tests.zig +662 -0
  75. data/ext/tb_client/tigerbeetle/src/io/common.zig +155 -0
  76. data/ext/tb_client/tigerbeetle/src/io/darwin.zig +1093 -0
  77. data/ext/tb_client/tigerbeetle/src/io/linux.zig +1880 -0
  78. data/ext/tb_client/tigerbeetle/src/io/test.zig +1005 -0
  79. data/ext/tb_client/tigerbeetle/src/io/windows.zig +1598 -0
  80. data/ext/tb_client/tigerbeetle/src/io.zig +34 -0
  81. data/ext/tb_client/tigerbeetle/src/iops.zig +134 -0
  82. data/ext/tb_client/tigerbeetle/src/list.zig +236 -0
  83. data/ext/tb_client/tigerbeetle/src/lsm/binary_search.zig +848 -0
  84. data/ext/tb_client/tigerbeetle/src/lsm/binary_search_benchmark.zig +179 -0
  85. data/ext/tb_client/tigerbeetle/src/lsm/cache_map.zig +424 -0
  86. data/ext/tb_client/tigerbeetle/src/lsm/cache_map_fuzz.zig +420 -0
  87. data/ext/tb_client/tigerbeetle/src/lsm/compaction.zig +2117 -0
  88. data/ext/tb_client/tigerbeetle/src/lsm/composite_key.zig +182 -0
  89. data/ext/tb_client/tigerbeetle/src/lsm/forest.zig +1119 -0
  90. data/ext/tb_client/tigerbeetle/src/lsm/forest_fuzz.zig +1102 -0
  91. data/ext/tb_client/tigerbeetle/src/lsm/forest_table_iterator.zig +200 -0
  92. data/ext/tb_client/tigerbeetle/src/lsm/groove.zig +1495 -0
  93. data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge.zig +739 -0
  94. data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge_benchmark.zig +166 -0
  95. data/ext/tb_client/tigerbeetle/src/lsm/manifest.zig +754 -0
  96. data/ext/tb_client/tigerbeetle/src/lsm/manifest_level.zig +1294 -0
  97. data/ext/tb_client/tigerbeetle/src/lsm/manifest_level_fuzz.zig +510 -0
  98. data/ext/tb_client/tigerbeetle/src/lsm/manifest_log.zig +1263 -0
  99. data/ext/tb_client/tigerbeetle/src/lsm/manifest_log_fuzz.zig +628 -0
  100. data/ext/tb_client/tigerbeetle/src/lsm/node_pool.zig +247 -0
  101. data/ext/tb_client/tigerbeetle/src/lsm/scan_buffer.zig +116 -0
  102. data/ext/tb_client/tigerbeetle/src/lsm/scan_builder.zig +543 -0
  103. data/ext/tb_client/tigerbeetle/src/lsm/scan_fuzz.zig +938 -0
  104. data/ext/tb_client/tigerbeetle/src/lsm/scan_lookup.zig +293 -0
  105. data/ext/tb_client/tigerbeetle/src/lsm/scan_merge.zig +362 -0
  106. data/ext/tb_client/tigerbeetle/src/lsm/scan_range.zig +99 -0
  107. data/ext/tb_client/tigerbeetle/src/lsm/scan_state.zig +17 -0
  108. data/ext/tb_client/tigerbeetle/src/lsm/scan_tree.zig +1036 -0
  109. data/ext/tb_client/tigerbeetle/src/lsm/schema.zig +617 -0
  110. data/ext/tb_client/tigerbeetle/src/lsm/scratch_memory.zig +84 -0
  111. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array.zig +1500 -0
  112. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_benchmark.zig +149 -0
  113. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_fuzz.zig +7 -0
  114. data/ext/tb_client/tigerbeetle/src/lsm/set_associative_cache.zig +865 -0
  115. data/ext/tb_client/tigerbeetle/src/lsm/table.zig +607 -0
  116. data/ext/tb_client/tigerbeetle/src/lsm/table_memory.zig +843 -0
  117. data/ext/tb_client/tigerbeetle/src/lsm/table_value_iterator.zig +105 -0
  118. data/ext/tb_client/tigerbeetle/src/lsm/timestamp_range.zig +40 -0
  119. data/ext/tb_client/tigerbeetle/src/lsm/tree.zig +630 -0
  120. data/ext/tb_client/tigerbeetle/src/lsm/tree_fuzz.zig +933 -0
  121. data/ext/tb_client/tigerbeetle/src/lsm/zig_zag_merge.zig +557 -0
  122. data/ext/tb_client/tigerbeetle/src/message_buffer.zig +469 -0
  123. data/ext/tb_client/tigerbeetle/src/message_bus.zig +1214 -0
  124. data/ext/tb_client/tigerbeetle/src/message_bus_fuzz.zig +936 -0
  125. data/ext/tb_client/tigerbeetle/src/message_pool.zig +343 -0
  126. data/ext/tb_client/tigerbeetle/src/multiversion.zig +2195 -0
  127. data/ext/tb_client/tigerbeetle/src/queue.zig +390 -0
  128. data/ext/tb_client/tigerbeetle/src/repl/completion.zig +201 -0
  129. data/ext/tb_client/tigerbeetle/src/repl/parser.zig +1356 -0
  130. data/ext/tb_client/tigerbeetle/src/repl/terminal.zig +496 -0
  131. data/ext/tb_client/tigerbeetle/src/repl.zig +1034 -0
  132. data/ext/tb_client/tigerbeetle/src/scripts/amqp.zig +973 -0
  133. data/ext/tb_client/tigerbeetle/src/scripts/cfo.zig +1866 -0
  134. data/ext/tb_client/tigerbeetle/src/scripts/changelog.zig +304 -0
  135. data/ext/tb_client/tigerbeetle/src/scripts/ci.zig +227 -0
  136. data/ext/tb_client/tigerbeetle/src/scripts/client_readmes.zig +658 -0
  137. data/ext/tb_client/tigerbeetle/src/scripts/devhub.zig +466 -0
  138. data/ext/tb_client/tigerbeetle/src/scripts/release.zig +1058 -0
  139. data/ext/tb_client/tigerbeetle/src/scripts.zig +105 -0
  140. data/ext/tb_client/tigerbeetle/src/shell.zig +1195 -0
  141. data/ext/tb_client/tigerbeetle/src/stack.zig +260 -0
  142. data/ext/tb_client/tigerbeetle/src/state_machine/auditor.zig +911 -0
  143. data/ext/tb_client/tigerbeetle/src/state_machine/workload.zig +2079 -0
  144. data/ext/tb_client/tigerbeetle/src/state_machine.zig +4872 -0
  145. data/ext/tb_client/tigerbeetle/src/state_machine_fuzz.zig +288 -0
  146. data/ext/tb_client/tigerbeetle/src/state_machine_tests.zig +3128 -0
  147. data/ext/tb_client/tigerbeetle/src/static_allocator.zig +82 -0
  148. data/ext/tb_client/tigerbeetle/src/stdx/bit_set.zig +157 -0
  149. data/ext/tb_client/tigerbeetle/src/stdx/bounded_array.zig +292 -0
  150. data/ext/tb_client/tigerbeetle/src/stdx/debug.zig +65 -0
  151. data/ext/tb_client/tigerbeetle/src/stdx/flags.zig +1414 -0
  152. data/ext/tb_client/tigerbeetle/src/stdx/mlock.zig +92 -0
  153. data/ext/tb_client/tigerbeetle/src/stdx/prng.zig +677 -0
  154. data/ext/tb_client/tigerbeetle/src/stdx/radix.zig +336 -0
  155. data/ext/tb_client/tigerbeetle/src/stdx/ring_buffer.zig +511 -0
  156. data/ext/tb_client/tigerbeetle/src/stdx/sort_test.zig +112 -0
  157. data/ext/tb_client/tigerbeetle/src/stdx/stdx.zig +1160 -0
  158. data/ext/tb_client/tigerbeetle/src/stdx/testing/low_level_hash_vectors.zig +142 -0
  159. data/ext/tb_client/tigerbeetle/src/stdx/testing/snaptest.zig +361 -0
  160. data/ext/tb_client/tigerbeetle/src/stdx/time_units.zig +275 -0
  161. data/ext/tb_client/tigerbeetle/src/stdx/unshare.zig +295 -0
  162. data/ext/tb_client/tigerbeetle/src/stdx/vendored/aegis.zig +436 -0
  163. data/ext/tb_client/tigerbeetle/src/stdx/windows.zig +48 -0
  164. data/ext/tb_client/tigerbeetle/src/stdx/zipfian.zig +402 -0
  165. data/ext/tb_client/tigerbeetle/src/storage.zig +489 -0
  166. data/ext/tb_client/tigerbeetle/src/storage_fuzz.zig +180 -0
  167. data/ext/tb_client/tigerbeetle/src/testing/bench.zig +146 -0
  168. data/ext/tb_client/tigerbeetle/src/testing/cluster/grid_checker.zig +53 -0
  169. data/ext/tb_client/tigerbeetle/src/testing/cluster/journal_checker.zig +61 -0
  170. data/ext/tb_client/tigerbeetle/src/testing/cluster/manifest_checker.zig +76 -0
  171. data/ext/tb_client/tigerbeetle/src/testing/cluster/message_bus.zig +110 -0
  172. data/ext/tb_client/tigerbeetle/src/testing/cluster/network.zig +412 -0
  173. data/ext/tb_client/tigerbeetle/src/testing/cluster/state_checker.zig +331 -0
  174. data/ext/tb_client/tigerbeetle/src/testing/cluster/storage_checker.zig +458 -0
  175. data/ext/tb_client/tigerbeetle/src/testing/cluster.zig +1198 -0
  176. data/ext/tb_client/tigerbeetle/src/testing/exhaustigen.zig +128 -0
  177. data/ext/tb_client/tigerbeetle/src/testing/fixtures.zig +181 -0
  178. data/ext/tb_client/tigerbeetle/src/testing/fuzz.zig +144 -0
  179. data/ext/tb_client/tigerbeetle/src/testing/id.zig +97 -0
  180. data/ext/tb_client/tigerbeetle/src/testing/io.zig +317 -0
  181. data/ext/tb_client/tigerbeetle/src/testing/marks.zig +126 -0
  182. data/ext/tb_client/tigerbeetle/src/testing/packet_simulator.zig +533 -0
  183. data/ext/tb_client/tigerbeetle/src/testing/reply_sequence.zig +154 -0
  184. data/ext/tb_client/tigerbeetle/src/testing/state_machine.zig +389 -0
  185. data/ext/tb_client/tigerbeetle/src/testing/storage.zig +1247 -0
  186. data/ext/tb_client/tigerbeetle/src/testing/table.zig +249 -0
  187. data/ext/tb_client/tigerbeetle/src/testing/time.zig +98 -0
  188. data/ext/tb_client/tigerbeetle/src/testing/tmp_tigerbeetle.zig +212 -0
  189. data/ext/tb_client/tigerbeetle/src/testing/vortex/constants.zig +26 -0
  190. data/ext/tb_client/tigerbeetle/src/testing/vortex/faulty_network.zig +580 -0
  191. data/ext/tb_client/tigerbeetle/src/testing/vortex/java_driver/ci.zig +39 -0
  192. data/ext/tb_client/tigerbeetle/src/testing/vortex/logged_process.zig +214 -0
  193. data/ext/tb_client/tigerbeetle/src/testing/vortex/rust_driver/ci.zig +34 -0
  194. data/ext/tb_client/tigerbeetle/src/testing/vortex/supervisor.zig +766 -0
  195. data/ext/tb_client/tigerbeetle/src/testing/vortex/workload.zig +543 -0
  196. data/ext/tb_client/tigerbeetle/src/testing/vortex/zig_driver.zig +181 -0
  197. data/ext/tb_client/tigerbeetle/src/tidy.zig +1448 -0
  198. data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_driver.zig +227 -0
  199. data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_load.zig +1069 -0
  200. data/ext/tb_client/tigerbeetle/src/tigerbeetle/cli.zig +1422 -0
  201. data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect.zig +1658 -0
  202. data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect_integrity.zig +518 -0
  203. data/ext/tb_client/tigerbeetle/src/tigerbeetle/libtb_client.zig +36 -0
  204. data/ext/tb_client/tigerbeetle/src/tigerbeetle/main.zig +646 -0
  205. data/ext/tb_client/tigerbeetle/src/tigerbeetle.zig +958 -0
  206. data/ext/tb_client/tigerbeetle/src/time.zig +236 -0
  207. data/ext/tb_client/tigerbeetle/src/trace/event.zig +745 -0
  208. data/ext/tb_client/tigerbeetle/src/trace/statsd.zig +462 -0
  209. data/ext/tb_client/tigerbeetle/src/trace.zig +556 -0
  210. data/ext/tb_client/tigerbeetle/src/unit_tests.zig +321 -0
  211. data/ext/tb_client/tigerbeetle/src/vopr.zig +1785 -0
  212. data/ext/tb_client/tigerbeetle/src/vortex.zig +101 -0
  213. data/ext/tb_client/tigerbeetle/src/vsr/checkpoint_trailer.zig +473 -0
  214. data/ext/tb_client/tigerbeetle/src/vsr/checksum.zig +208 -0
  215. data/ext/tb_client/tigerbeetle/src/vsr/checksum_benchmark.zig +43 -0
  216. data/ext/tb_client/tigerbeetle/src/vsr/client.zig +768 -0
  217. data/ext/tb_client/tigerbeetle/src/vsr/client_replies.zig +532 -0
  218. data/ext/tb_client/tigerbeetle/src/vsr/client_sessions.zig +338 -0
  219. data/ext/tb_client/tigerbeetle/src/vsr/clock.zig +1019 -0
  220. data/ext/tb_client/tigerbeetle/src/vsr/fault_detector.zig +279 -0
  221. data/ext/tb_client/tigerbeetle/src/vsr/free_set.zig +1381 -0
  222. data/ext/tb_client/tigerbeetle/src/vsr/free_set_fuzz.zig +315 -0
  223. data/ext/tb_client/tigerbeetle/src/vsr/grid.zig +1460 -0
  224. data/ext/tb_client/tigerbeetle/src/vsr/grid_blocks_missing.zig +757 -0
  225. data/ext/tb_client/tigerbeetle/src/vsr/grid_scrubber.zig +797 -0
  226. data/ext/tb_client/tigerbeetle/src/vsr/journal.zig +2586 -0
  227. data/ext/tb_client/tigerbeetle/src/vsr/marzullo.zig +308 -0
  228. data/ext/tb_client/tigerbeetle/src/vsr/message_header.zig +1777 -0
  229. data/ext/tb_client/tigerbeetle/src/vsr/multi_batch.zig +715 -0
  230. data/ext/tb_client/tigerbeetle/src/vsr/multi_batch_fuzz.zig +185 -0
  231. data/ext/tb_client/tigerbeetle/src/vsr/repair_budget.zig +333 -0
  232. data/ext/tb_client/tigerbeetle/src/vsr/replica.zig +12355 -0
  233. data/ext/tb_client/tigerbeetle/src/vsr/replica_format.zig +416 -0
  234. data/ext/tb_client/tigerbeetle/src/vsr/replica_reformat.zig +165 -0
  235. data/ext/tb_client/tigerbeetle/src/vsr/replica_test.zig +2910 -0
  236. data/ext/tb_client/tigerbeetle/src/vsr/routing.zig +1075 -0
  237. data/ext/tb_client/tigerbeetle/src/vsr/superblock.zig +1603 -0
  238. data/ext/tb_client/tigerbeetle/src/vsr/superblock_fuzz.zig +484 -0
  239. data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums.zig +405 -0
  240. data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +355 -0
  241. data/ext/tb_client/tigerbeetle/src/vsr/sync.zig +29 -0
  242. data/ext/tb_client/tigerbeetle/src/vsr.zig +1727 -0
  243. data/lib/tb_client/shared_lib.rb +12 -5
  244. data/lib/tigerbeetle/client.rb +1 -1
  245. data/lib/tigerbeetle/platforms.rb +9 -0
  246. data/lib/tigerbeetle/version.rb +2 -2
  247. data/tigerbeetle.gemspec +22 -5
  248. metadata +242 -3
  249. data/ext/tb_client/pkg.tar.gz +0 -0
@@ -0,0 +1,190 @@
1
+ const std = @import("std");
2
+ const builtin = @import("builtin");
3
+ const jni = @import("jni.zig");
4
+
5
+ const log = std.log.scoped(.tb_client_jni);
6
+ const assert = std.debug.assert;
7
+
8
+ /// Helper for managing the `AttachCurrentThread`/`DetachCurrentThread` lifecycle
9
+ /// when the JNI layer is unaware of when the native thread exits.
10
+ /// https://developer.android.com/training/articles/perf-jni#threads
11
+ pub const JNIThreadCleaner = struct {
12
+ var tls_key: ?tls.Key = null;
13
+ var create_key_once = std.once(create_key);
14
+
15
+ /// This function calls `AttachCurrentThreadAsDaemon` to attach the current native thread to
16
+ /// the JVM as a daemon thread. It also registers a callback to call `DetachCurrentThread`
17
+ /// when the thread exits (e.g., when the client is closed or evicted).
18
+ pub fn attach_current_thread_with_cleanup(jvm: *jni.JavaVM) *jni.JNIEnv {
19
+ // Create the tls key once per JVM.
20
+ create_key_once.call();
21
+
22
+ // Set the JVM handler to the thread-local storage slot for each time a native
23
+ // thread is started.
24
+ tls.set_key(tls_key.?, jvm);
25
+
26
+ return attach_current_thread(jvm);
27
+ }
28
+
29
+ /// Create the thread-local storage key and the corresponding destructor callback.
30
+ /// Note: We don't need to delete the key because the JNI module cannot be unloaded,
31
+ /// so it will always be available for the duration of the JVM process.
32
+ fn create_key() void {
33
+ assert(tls_key == null);
34
+ tls_key = tls.create_key(&destructor_callback);
35
+ }
36
+
37
+ // Will be called by the OS with the JVM handler when the thread finalizes.
38
+ fn destructor_callback(jvm: *anyopaque) callconv(.c) void {
39
+ assert(tls_key != null);
40
+ detach_current_thread(@ptrCast(jvm));
41
+ }
42
+
43
+ fn attach_current_thread(jvm: *jni.JavaVM) *jni.JNIEnv {
44
+ var env: *jni.JNIEnv = undefined;
45
+ const jni_result = jvm.attach_current_thread_as_daemon(&env, null);
46
+ if (jni_result != .ok) {
47
+ const message = "Unexpected result calling JavaVM.AttachCurrentThreadAsDaemon";
48
+ log.err(
49
+ message ++ "; Error = {} ({s})",
50
+ .{ @intFromEnum(jni_result), @tagName(jni_result) },
51
+ );
52
+ @panic("JNI: " ++ message);
53
+ }
54
+
55
+ return env;
56
+ }
57
+
58
+ fn detach_current_thread(jvm: *jni.JavaVM) void {
59
+ const jni_result = jvm.detach_current_thread();
60
+ if (jni_result != .ok) {
61
+ const message = "Unexpected result calling JavaVM.DetachCurrentThread";
62
+ log.err(
63
+ message ++ "; Error = {} ({s})",
64
+ .{ @intFromEnum(jni_result), @tagName(jni_result) },
65
+ );
66
+ @panic("JNI: " ++ message);
67
+ }
68
+ }
69
+
70
+ /// Thread-local storage abstraction,
71
+ /// based on `pthread_key_create` for Linux/MacOS and `FlsAlloc` for Windows.
72
+ const tls = switch (builtin.os.tag) {
73
+ .linux, .macos => struct {
74
+ const Key = std.c.pthread_key_t;
75
+
76
+ fn create_key(destructor: ?*const fn (value: *anyopaque) callconv(.c) void) Key {
77
+ var key: Key = undefined;
78
+ const ret = std.c.pthread_key_create(&key, destructor);
79
+ if (ret != .SUCCESS) {
80
+ const message = "Unexpected result calling pthread_key_create";
81
+ log.err(message ++ "; Error = {} ({s})", .{
82
+ @intFromEnum(ret),
83
+ @tagName(ret),
84
+ });
85
+ @panic("JNI: " ++ message);
86
+ }
87
+
88
+ return key;
89
+ }
90
+
91
+ fn set_key(key: Key, value: *anyopaque) void {
92
+ const ret = std.c.pthread_setspecific(key, value);
93
+ if (ret != 0) {
94
+ const message = "Unexpected result calling pthread_setspecific";
95
+ log.err(message ++ "; Error = {}", .{ret});
96
+ @panic("JNI: " ++ message);
97
+ }
98
+ }
99
+ },
100
+ .windows => struct {
101
+ const windows = struct {
102
+ const FLS_OUT_OF_INDEXES: std.os.windows.DWORD = 0xffffffff;
103
+ // https://learn.microsoft.com/en-us/windows/win32/api/fibersapi/nf-fibersapi-flsalloc
104
+ extern "kernel32" fn FlsAlloc(
105
+ ?*const fn (value: *anyopaque) callconv(.c) void,
106
+ ) callconv(.c) std.os.windows.DWORD;
107
+ // https://learn.microsoft.com/en-us/windows/win32/api/fibersapi/nf-fibersapi-flssetvalue
108
+ extern "kernel32" fn FlsSetValue(
109
+ std.os.windows.DWORD,
110
+ *anyopaque,
111
+ ) callconv(.c) std.os.windows.BOOL;
112
+ };
113
+
114
+ const Key = std.os.windows.DWORD;
115
+
116
+ fn create_key(destructor: ?*const fn (value: *anyopaque) callconv(.c) void) Key {
117
+ const key = windows.FlsAlloc(destructor);
118
+ if (key == windows.FLS_OUT_OF_INDEXES) {
119
+ const message = "Unexpected result calling FlsAlloc";
120
+ log.err(message ++ "; Error = {}", .{key});
121
+ @panic("JNI: " ++ message);
122
+ }
123
+
124
+ return key;
125
+ }
126
+
127
+ fn set_key(key: Key, value: *anyopaque) void {
128
+ const ret = windows.FlsSetValue(key, value);
129
+ if (ret == std.os.windows.FALSE) {
130
+ const message = "Unexpected result calling FlsSetValue";
131
+ log.err(message ++ "; Error = {}", .{ret});
132
+ @panic("JNI: " ++ message);
133
+ }
134
+ }
135
+ },
136
+ else => unreachable,
137
+ };
138
+ };
139
+
140
+ test "JNIThreadCleaner:tls" {
141
+ const tls = JNIThreadCleaner.tls;
142
+ const TestContext = struct {
143
+ const TestContext = @This();
144
+
145
+ var tls_key: ?tls.Key = null;
146
+ var event: std.Thread.ResetEvent = .{};
147
+
148
+ counter: std.atomic.Value(u32),
149
+
150
+ fn init() TestContext {
151
+ if (tls_key == null) {
152
+ tls_key = tls.create_key(&destructor_callback);
153
+ }
154
+
155
+ return .{
156
+ .counter = std.atomic.Value(u32).init(0),
157
+ };
158
+ }
159
+
160
+ fn thread_main(self: *TestContext) void {
161
+ tls.set_key(tls_key.?, self);
162
+ event.wait();
163
+ }
164
+
165
+ fn destructor_callback(tls_value: *anyopaque) callconv(.c) void {
166
+ assert(tls_key != null);
167
+
168
+ const self: *TestContext = @ptrCast(@alignCast(tls_value));
169
+ _ = self.counter.fetchAdd(1, .monotonic);
170
+ }
171
+ };
172
+
173
+ var context = TestContext.init();
174
+ var threads: [10]std.Thread = undefined;
175
+ for (&threads) |*thread| {
176
+ thread.* = try std.Thread.spawn(.{}, TestContext.thread_main, .{&context});
177
+ }
178
+
179
+ // Assert that the callback only fires when the thread finishes.
180
+ try std.testing.expect(context.counter.load(.monotonic) == 0);
181
+
182
+ // Signal all threads to complete and wait for them.
183
+ TestContext.event.set();
184
+ for (&threads) |*thread| {
185
+ thread.join();
186
+ }
187
+
188
+ // Assert that all callbacks have fired.
189
+ try std.testing.expect(context.counter.load(.monotonic) == threads.len);
190
+ }
@@ -0,0 +1,104 @@
1
+ const std = @import("std");
2
+ const builtin = @import("builtin");
3
+ const log = std.log;
4
+ const assert = std.debug.assert;
5
+
6
+ const Shell = @import("../../shell.zig");
7
+ const TmpTigerBeetle = @import("../../testing/tmp_tigerbeetle.zig");
8
+
9
+ pub fn tests(shell: *Shell, gpa: std.mem.Allocator) !void {
10
+ assert(shell.file_exists("package.json"));
11
+
12
+ try shell.exec_zig("build clients:node -Drelease", .{});
13
+
14
+ // Integration tests.
15
+
16
+ // We need to build the tigerbeetle-node library manually for samples/testers to work.
17
+ try shell.exec("npm install", .{});
18
+
19
+ for ([_][]const u8{ "test", "benchmark" }) |tester| {
20
+ log.info("testing {s}s", .{tester});
21
+
22
+ var tmp_beetle = try TmpTigerBeetle.init(gpa, .{
23
+ .development = true,
24
+ });
25
+ defer tmp_beetle.deinit(gpa);
26
+ errdefer tmp_beetle.log_stderr();
27
+
28
+ try shell.env.put("TB_ADDRESS", tmp_beetle.port_str);
29
+ try shell.exec("node ./dist/{tester}", .{ .tester = tester });
30
+ }
31
+
32
+ inline for ([_][]const u8{ "basic", "two-phase", "two-phase-many", "walkthrough" }) |sample| {
33
+ log.info("testing sample '{s}'", .{sample});
34
+
35
+ try shell.pushd("./samples/" ++ sample);
36
+ defer shell.popd();
37
+
38
+ var tmp_beetle = try TmpTigerBeetle.init(gpa, .{
39
+ .development = true,
40
+ });
41
+ defer tmp_beetle.deinit(gpa);
42
+ errdefer tmp_beetle.log_stderr();
43
+
44
+ try shell.env.put("TB_ADDRESS", tmp_beetle.port_str);
45
+ try shell.exec("npm install", .{});
46
+ try shell.exec("node main.js", .{});
47
+ }
48
+
49
+ // Container smoke tests.
50
+ if (builtin.target.os.tag == .linux) {
51
+ try shell.exec("npm pack --quiet", .{});
52
+
53
+ for ([_][]const u8{ "node:18", "node:18-alpine" }) |image| {
54
+ log.info("testing docker image: '{s}'", .{image});
55
+
56
+ try shell.exec(
57
+ \\docker run
58
+ \\--security-opt seccomp=unconfined
59
+ \\--volume ./:/host
60
+ \\{image}
61
+ \\sh
62
+ \\-c {script}
63
+ , .{
64
+ .image = image,
65
+ .script =
66
+ \\set -ex
67
+ \\mkdir test-project && cd test-project
68
+ \\npm install /host/tigerbeetle-node-*.tgz
69
+ \\node -e 'require("tigerbeetle-node"); console.log("SUCCESS!")'
70
+ ,
71
+ });
72
+ }
73
+ }
74
+ }
75
+
76
+ pub fn validate_release(shell: *Shell, gpa: std.mem.Allocator, options: struct {
77
+ version: []const u8,
78
+ tigerbeetle: []const u8,
79
+ }) !void {
80
+ var tmp_beetle = try TmpTigerBeetle.init(gpa, .{
81
+ .development = true,
82
+ .prebuilt = options.tigerbeetle,
83
+ });
84
+ defer tmp_beetle.deinit(gpa);
85
+ errdefer tmp_beetle.log_stderr();
86
+
87
+ try shell.env.put("TB_ADDRESS", tmp_beetle.port_str);
88
+
89
+ try shell.exec("npm install tigerbeetle-node@{version}", .{
90
+ .version = options.version,
91
+ });
92
+
93
+ try Shell.copy_path(
94
+ shell.project_root,
95
+ "src/clients/node/samples/basic/main.js",
96
+ shell.cwd,
97
+ "main.js",
98
+ );
99
+ try shell.exec("node main.js", .{});
100
+ }
101
+
102
+ pub fn release_published_latest(shell: *Shell) ![]const u8 {
103
+ return try shell.exec_stdout("npm view tigerbeetle-node version", .{});
104
+ }
@@ -0,0 +1,75 @@
1
+ const Docs = @import("../docs_types.zig").Docs;
2
+
3
+ pub const NodeDocs = Docs{
4
+ .directory = "node",
5
+
6
+ .markdown_name = "javascript",
7
+ .extension = "js",
8
+ .proper_name = "Node.js",
9
+
10
+ .test_source_path = "",
11
+
12
+ .name = "tigerbeetle-node",
13
+ .description =
14
+ \\The TigerBeetle client for Node.js.
15
+ ,
16
+ .prerequisites =
17
+ \\* Node.js >= `18`
18
+ ,
19
+
20
+ .project_file = "",
21
+ .project_file_name = "",
22
+ .test_file_name = "main",
23
+
24
+ .install_commands = "npm install --save-exact tigerbeetle-node",
25
+ .run_commands = "node main.js",
26
+
27
+ .examples =
28
+ \\### Sidenote: `BigInt`
29
+ \\TigerBeetle uses 64-bit integers for many fields while JavaScript's
30
+ \\builtin `Number` maximum value is `2^53-1`. The `n` suffix in JavaScript
31
+ \\means the value is a `BigInt`. This is useful for literal numbers. If
32
+ \\you already have a `Number` variable though, you can call the `BigInt`
33
+ \\constructor to get a `BigInt` from it. For example, `1n` is the same as
34
+ \\`BigInt(1)`.
35
+ ,
36
+
37
+ .client_object_documentation = "",
38
+ .create_accounts_documentation = "",
39
+ .account_flags_documentation =
40
+ \\To toggle behavior for an account, combine enum values stored in the
41
+ \\`AccountFlags` object (in TypeScript it is an actual enum) with
42
+ \\bitwise-or:
43
+ \\
44
+ \\* `AccountFlags.linked`
45
+ \\* `AccountFlags.debits_must_not_exceed_credits`
46
+ \\* `AccountFlags.credits_must_not_exceed_credits`
47
+ \\* `AccountFlags.history`
48
+ \\
49
+ ,
50
+
51
+ .create_accounts_errors_documentation =
52
+ \\To handle errors you can either 1) exactly match error codes returned
53
+ \\from `client.createAccounts` with enum values in the
54
+ \\`CreateAccountError` object, or you can 2) look up the error code in
55
+ \\the `CreateAccountError` object for a human-readable string.
56
+ ,
57
+ .create_transfers_documentation = "",
58
+ .create_transfers_errors_documentation =
59
+ \\To handle errors you can either 1) exactly match error codes returned
60
+ \\from `client.createTransfers` with enum values in the
61
+ \\`CreateTransferError` object, or you can 2) look up the error code in
62
+ \\the `CreateTransferError` object for a human-readable string.
63
+ ,
64
+
65
+ .transfer_flags_documentation =
66
+ \\To toggle behavior for a transfer, combine enum values stored in the
67
+ \\`TransferFlags` object (in TypeScript it is an actual enum) with
68
+ \\bitwise-or:
69
+ \\
70
+ \\* `TransferFlags.linked`
71
+ \\* `TransferFlags.pending`
72
+ \\* `TransferFlags.post_pending_transfer`
73
+ \\* `TransferFlags.void_pending_transfer`
74
+ ,
75
+ };