rubydb 0.1.3 → 0.1.5

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 (420) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +15 -15
  3. data/.github/workflows/benchmark.yml +26 -26
  4. data/.github/workflows/compatibility.yml +63 -63
  5. data/.github/workflows/fuzz.yml +33 -33
  6. data/.github/workflows/lint.yml +21 -21
  7. data/.github/workflows/operations.yml +24 -24
  8. data/.github/workflows/production-validation.yml +111 -111
  9. data/.github/workflows/release.yml +77 -77
  10. data/.github/workflows/security.yml +39 -37
  11. data/.github/workflows/test.yml +26 -26
  12. data/.github/workflows/workload.yml +58 -58
  13. data/.gitignore +12 -5
  14. data/.rubocop.yml +50 -44
  15. data/.standard.yml +9 -14
  16. data/ARCHITECTURE.md +21 -21
  17. data/CHANGELOG.md +49 -27
  18. data/CODE_OF_CONDUCT.md +13 -13
  19. data/CONTRIBUTING.md +29 -29
  20. data/GOVERNANCE.md +16 -16
  21. data/Gemfile +18 -17
  22. data/Gemfile.lock +125 -71
  23. data/README.md +249 -162
  24. data/ROADMAP.md +27 -27
  25. data/Rakefile +71 -71
  26. data/SECURITY.md +54 -54
  27. data/SUPPORT.md +14 -14
  28. data/adapters/activerecord/Gemfile +11 -11
  29. data/adapters/activerecord/lib/active_record/connection_adapters/rubydb_adapter.rb +877 -880
  30. data/adapters/activerecord/rubydb-activerecord.gemspec +21 -21
  31. data/adapters/activerecord/spec/rubydb_adapter_integration_spec.rb +155 -143
  32. data/adapters/ruby/README.md +18 -18
  33. data/adapters/sequel/README.md +11 -11
  34. data/config/monitoring/prometheus-alerts.yml +39 -39
  35. data/config/production.yml +36 -36
  36. data/docs/README.md +75 -71
  37. data/docs/architecture/concurrency.md +14 -14
  38. data/docs/architecture/current-state.md +125 -125
  39. data/docs/architecture/execution-engine.md +25 -25
  40. data/docs/architecture/indexes.md +19 -19
  41. data/docs/architecture/mvcc.md +19 -19
  42. data/docs/architecture/overview.md +13 -13
  43. data/docs/architecture/pages.md +11 -11
  44. data/docs/architecture/production-roadmap.md +82 -82
  45. data/docs/architecture/query-planner.md +20 -20
  46. data/docs/architecture/recovery.md +18 -18
  47. data/docs/architecture/sql-engine.md +12 -12
  48. data/docs/architecture/storage-engine.md +14 -14
  49. data/docs/architecture/transactions.md +10 -10
  50. data/docs/architecture/wal.md +28 -28
  51. data/docs/cli-cheatsheet.md +98 -98
  52. data/docs/cli.md +275 -275
  53. data/docs/contributing/architecture.md +9 -9
  54. data/docs/contributing/benchmarking.md +14 -14
  55. data/docs/contributing/development.md +16 -16
  56. data/docs/contributing/release-process.md +49 -49
  57. data/docs/contributing/testing.md +16 -16
  58. data/docs/debugging.md +229 -229
  59. data/docs/developer/branching.md +10 -10
  60. data/docs/developer/database-diff.md +10 -10
  61. data/docs/developer/local-development.md +17 -17
  62. data/docs/developer/snapshots.md +9 -9
  63. data/docs/developer/temporal-data.md +10 -10
  64. data/docs/developer-guide.md +297 -297
  65. data/docs/getting-started/first-database.md +16 -16
  66. data/docs/getting-started/first-query.md +13 -13
  67. data/docs/getting-started/installation.md +19 -19
  68. data/docs/getting-started/local-to-production.md +300 -300
  69. data/docs/getting-started/quickstart.md +17 -17
  70. data/docs/getting-started/rails.md +16 -16
  71. data/docs/hardening_backlog.md +93 -93
  72. data/docs/lessons-learned.md +112 -112
  73. data/docs/operations/backups.md +33 -33
  74. data/docs/operations/disaster-recovery.md +31 -31
  75. data/docs/operations/failover.md +30 -30
  76. data/docs/operations/monitoring.md +25 -25
  77. data/docs/operations/production-guide.md +295 -295
  78. data/docs/operations/production-runbook.md +45 -45
  79. data/docs/operations/replication.md +33 -33
  80. data/docs/operations/restore.md +6 -6
  81. data/docs/operations/runbook.md +34 -34
  82. data/docs/operations/upgrades.md +14 -14
  83. data/docs/operations/workload-testing.md +17 -17
  84. data/docs/production-readiness.md +118 -118
  85. data/docs/production_validation.md +150 -150
  86. data/docs/rails/active-record.md +11 -11
  87. data/docs/rails/compatibility-guide.md +90 -90
  88. data/docs/rails/database-yml.md +92 -92
  89. data/docs/rails/installation.md +17 -17
  90. data/docs/rails/migrations.md +17 -17
  91. data/docs/rails/production.md +82 -82
  92. data/docs/rails/troubleshooting.md +18 -18
  93. data/docs/release.md +25 -25
  94. data/docs/server/architecture.md +10 -10
  95. data/docs/server/authentication.md +10 -10
  96. data/docs/server/configuration.md +16 -16
  97. data/docs/server/connection-pooling.md +10 -10
  98. data/docs/server/deployment.md +10 -10
  99. data/docs/server/protocol.md +12 -12
  100. data/docs/sql/compatibility-guide.md +82 -82
  101. data/docs/sql/compatibility.md +39 -39
  102. data/docs/sql/data-types.md +10 -10
  103. data/docs/sql/functions.md +9 -9
  104. data/docs/sql/joins.md +9 -9
  105. data/docs/sql/operators.md +9 -9
  106. data/docs/sql/sqlite-compatibility.md +21 -21
  107. data/docs/sql/syntax.md +10 -10
  108. data/docs/sql/transactions.md +10 -10
  109. data/docs/troubleshooting.md +244 -244
  110. data/lessons/01-foundations.md +73 -0
  111. data/lessons/02-local-development.md +121 -0
  112. data/lessons/03-embedded-rubydb.md +99 -0
  113. data/lessons/04-rails-complex-apps.md +138 -0
  114. data/lessons/05-rubydb-production-server.md +237 -0
  115. data/lessons/06-postgresql-massive-apps.md +96 -0
  116. data/lessons/07-hybrid-microservices.md +94 -0
  117. data/lessons/08-migrations-backups-recovery.md +86 -0
  118. data/lessons/09-observability-security-scale.md +87 -0
  119. data/lessons/10-release-readiness.md +125 -0
  120. data/lib/rubydb/backup/archive.rb +332 -334
  121. data/lib/rubydb/backup/backup.rb +400 -401
  122. data/lib/rubydb/backup/incremental.rb +349 -353
  123. data/lib/rubydb/backup/restore.rb +289 -290
  124. data/lib/rubydb/backup/snapshot.rb +265 -267
  125. data/lib/rubydb/backup/verification.rb +276 -279
  126. data/lib/rubydb/branching/branch.rb +181 -181
  127. data/lib/rubydb/branching/branch_manager.rb +307 -311
  128. data/lib/rubydb/branching/branch_metadata.rb +140 -140
  129. data/lib/rubydb/branching/checkout.rb +165 -166
  130. data/lib/rubydb/branching/copy_on_write.rb +272 -272
  131. data/lib/rubydb/branching/diff.rb +137 -138
  132. data/lib/rubydb/branching/merge.rb +282 -285
  133. data/lib/rubydb/build_info.rb +15 -15
  134. data/lib/rubydb/catalog/catalog.rb +391 -391
  135. data/lib/rubydb/catalog/column.rb +112 -112
  136. data/lib/rubydb/catalog/constraint.rb +180 -180
  137. data/lib/rubydb/catalog/database.rb +184 -184
  138. data/lib/rubydb/catalog/index.rb +97 -97
  139. data/lib/rubydb/catalog/schema.rb +103 -103
  140. data/lib/rubydb/catalog/sequence.rb +90 -90
  141. data/lib/rubydb/catalog/system_catalog.rb +698 -698
  142. data/lib/rubydb/catalog/table.rb +178 -178
  143. data/lib/rubydb/catalog/trigger.rb +102 -102
  144. data/lib/rubydb/catalog/view.rb +66 -66
  145. data/lib/rubydb/cli/application.rb +163 -163
  146. data/lib/rubydb/cli/commands/backup.rb +80 -81
  147. data/lib/rubydb/cli/commands/branch.rb +72 -72
  148. data/lib/rubydb/cli/commands/checkout.rb +54 -54
  149. data/lib/rubydb/cli/commands/create.rb +58 -58
  150. data/lib/rubydb/cli/commands/diff.rb +76 -77
  151. data/lib/rubydb/cli/commands/doctor.rb +74 -74
  152. data/lib/rubydb/cli/commands/drop.rb +57 -57
  153. data/lib/rubydb/cli/commands/init.rb +101 -102
  154. data/lib/rubydb/cli/commands/inspect.rb +95 -95
  155. data/lib/rubydb/cli/commands/merge.rb +63 -63
  156. data/lib/rubydb/cli/commands/migrate.rb +62 -62
  157. data/lib/rubydb/cli/commands/restart.rb +42 -39
  158. data/lib/rubydb/cli/commands/restore.rb +121 -121
  159. data/lib/rubydb/cli/commands/shell.rb +365 -365
  160. data/lib/rubydb/cli/commands/snapshot.rb +79 -79
  161. data/lib/rubydb/cli/commands/start.rb +88 -82
  162. data/lib/rubydb/cli/commands/status.rb +96 -92
  163. data/lib/rubydb/cli/commands/stop.rb +47 -47
  164. data/lib/rubydb/cli/commands/vacuum.rb +58 -58
  165. data/lib/rubydb/cli/formatter.rb +221 -221
  166. data/lib/rubydb/cli/output.rb +168 -168
  167. data/lib/rubydb/client/client.rb +302 -304
  168. data/lib/rubydb/client/connection.rb +414 -415
  169. data/lib/rubydb/client/connection_pool.rb +168 -168
  170. data/lib/rubydb/client/connection_url.rb +96 -96
  171. data/lib/rubydb/client/prepared_statement.rb +60 -60
  172. data/lib/rubydb/client/result.rb +123 -123
  173. data/lib/rubydb/client/statement.rb +52 -52
  174. data/lib/rubydb/client/transaction.rb +130 -130
  175. data/lib/rubydb/concurrency/concurrency.rb +19 -19
  176. data/lib/rubydb/concurrency/deadlock_detector.rb +148 -150
  177. data/lib/rubydb/concurrency/latch.rb +101 -101
  178. data/lib/rubydb/concurrency/lock_graph.rb +163 -165
  179. data/lib/rubydb/concurrency/mutex.rb +181 -183
  180. data/lib/rubydb/concurrency/rw_lock.rb +180 -180
  181. data/lib/rubydb/concurrency/scheduler.rb +248 -250
  182. data/lib/rubydb/concurrency/worker_pool.rb +145 -143
  183. data/lib/rubydb/configuration/config.rb +170 -170
  184. data/lib/rubydb/configuration/defaults.rb +179 -179
  185. data/lib/rubydb/configuration/environment.rb +152 -152
  186. data/lib/rubydb/configuration/parser.rb +185 -185
  187. data/lib/rubydb/configuration/validation.rb +221 -221
  188. data/lib/rubydb/constants.rb +74 -74
  189. data/lib/rubydb/constraints/check.rb +181 -181
  190. data/lib/rubydb/constraints/constraint.rb +101 -101
  191. data/lib/rubydb/constraints/foreign_key.rb +130 -130
  192. data/lib/rubydb/constraints/not_null.rb +64 -64
  193. data/lib/rubydb/constraints/primary_key.rb +99 -99
  194. data/lib/rubydb/constraints/unique.rb +106 -108
  195. data/lib/rubydb/constraints/validator.rb +349 -350
  196. data/lib/rubydb/errors/authentication_error.rb +10 -10
  197. data/lib/rubydb/errors/authorization_error.rb +23 -23
  198. data/lib/rubydb/errors/client_error.rb +10 -10
  199. data/lib/rubydb/errors/configuration_error.rb +10 -10
  200. data/lib/rubydb/errors/connection_error.rb +10 -10
  201. data/lib/rubydb/errors/constraint_error.rb +23 -23
  202. data/lib/rubydb/errors/corruption_error.rb +10 -10
  203. data/lib/rubydb/errors/database_error.rb +10 -10
  204. data/lib/rubydb/errors/error.rb +20 -20
  205. data/lib/rubydb/errors/execution_error.rb +10 -10
  206. data/lib/rubydb/errors/parser_error.rb +10 -10
  207. data/lib/rubydb/errors/recovery_error.rb +10 -10
  208. data/lib/rubydb/errors/replication_error.rb +10 -10
  209. data/lib/rubydb/errors/server_error.rb +6 -6
  210. data/lib/rubydb/errors/storage_error.rb +10 -10
  211. data/lib/rubydb/errors/transaction_error.rb +10 -10
  212. data/lib/rubydb/execution/aggregate_executor.rb +134 -138
  213. data/lib/rubydb/execution/delete_executor.rb +110 -112
  214. data/lib/rubydb/execution/distinct_executor.rb +131 -135
  215. data/lib/rubydb/execution/executor.rb +1195 -1192
  216. data/lib/rubydb/execution/expression.rb +191 -193
  217. data/lib/rubydb/execution/index_scan.rb +142 -142
  218. data/lib/rubydb/execution/insert_executor.rb +215 -217
  219. data/lib/rubydb/execution/join_executor.rb +243 -249
  220. data/lib/rubydb/execution/limit_executor.rb +83 -85
  221. data/lib/rubydb/execution/optimizer.rb +227 -215
  222. data/lib/rubydb/execution/plan.rb +355 -353
  223. data/lib/rubydb/execution/planner.rb +542 -536
  224. data/lib/rubydb/execution/predicate.rb +235 -235
  225. data/lib/rubydb/execution/scan.rb +49 -49
  226. data/lib/rubydb/execution/sequential_scan.rb +63 -63
  227. data/lib/rubydb/execution/sort_executor.rb +180 -185
  228. data/lib/rubydb/execution/update_executor.rb +160 -162
  229. data/lib/rubydb/functions/aggregate.rb +70 -70
  230. data/lib/rubydb/functions/date_functions.rb +274 -278
  231. data/lib/rubydb/functions/function.rb +85 -85
  232. data/lib/rubydb/functions/json_functions.rb +231 -215
  233. data/lib/rubydb/functions/numeric_functions.rb +346 -346
  234. data/lib/rubydb/functions/scalar.rb +52 -52
  235. data/lib/rubydb/functions/string_functions.rb +383 -383
  236. data/lib/rubydb/functions/system_functions.rb +258 -246
  237. data/lib/rubydb/history/as_of.rb +238 -238
  238. data/lib/rubydb/history/change.rb +105 -105
  239. data/lib/rubydb/history/history.rb +131 -131
  240. data/lib/rubydb/history/history_manager.rb +228 -229
  241. data/lib/rubydb/history/temporal_query.rb +202 -202
  242. data/lib/rubydb/history/timeline.rb +144 -144
  243. data/lib/rubydb/indexes/btree.rb +186 -186
  244. data/lib/rubydb/indexes/btree_cursor.rb +258 -258
  245. data/lib/rubydb/indexes/btree_node.rb +384 -385
  246. data/lib/rubydb/indexes/hash_index.rb +150 -150
  247. data/lib/rubydb/indexes/index.rb +71 -71
  248. data/lib/rubydb/indexes/index_manager.rb +408 -406
  249. data/lib/rubydb/indexes/index_scan.rb +466 -470
  250. data/lib/rubydb/migrations/migration.rb +253 -254
  251. data/lib/rubydb/migrations/migration_lock.rb +146 -146
  252. data/lib/rubydb/migrations/migration_manager.rb +187 -176
  253. data/lib/rubydb/migrations/migration_version.rb +71 -71
  254. data/lib/rubydb/migrations/schema_diff.rb +211 -211
  255. data/lib/rubydb/migrations/schema_version.rb +64 -64
  256. data/lib/rubydb/monitoring/events.rb +155 -160
  257. data/lib/rubydb/monitoring/health.rb +216 -222
  258. data/lib/rubydb/monitoring/logger.rb +188 -193
  259. data/lib/rubydb/monitoring/metrics.rb +363 -359
  260. data/lib/rubydb/monitoring/performance.rb +176 -176
  261. data/lib/rubydb/monitoring/statistics.rb +168 -170
  262. data/lib/rubydb/mvcc/garbage_collector.rb +199 -199
  263. data/lib/rubydb/mvcc/mvcc.rb +16 -16
  264. data/lib/rubydb/mvcc/snapshot.rb +146 -147
  265. data/lib/rubydb/mvcc/vacuum.rb +180 -180
  266. data/lib/rubydb/mvcc/version.rb +106 -106
  267. data/lib/rubydb/mvcc/version_store.rb +396 -398
  268. data/lib/rubydb/mvcc/visibility.rb +107 -109
  269. data/lib/rubydb/protocol/capabilities.rb +125 -125
  270. data/lib/rubydb/protocol/decoder.rb +142 -145
  271. data/lib/rubydb/protocol/encoder.rb +131 -136
  272. data/lib/rubydb/protocol/handshake.rb +306 -305
  273. data/lib/rubydb/protocol/message.rb +121 -121
  274. data/lib/rubydb/protocol/parameter_binder.rb +101 -0
  275. data/lib/rubydb/protocol/protocol.rb +276 -277
  276. data/lib/rubydb/protocol/version.rb +54 -54
  277. data/lib/rubydb/rails/adapter.rb +245 -239
  278. data/lib/rubydb/rails/connection.rb +312 -314
  279. data/lib/rubydb/rails/database_statements.rb +122 -122
  280. data/lib/rubydb/rails/migration.rb +131 -131
  281. data/lib/rubydb/rails/quoting.rb +109 -109
  282. data/lib/rubydb/rails/result.rb +123 -120
  283. data/lib/rubydb/rails/schema_statements.rb +339 -339
  284. data/lib/rubydb/rails/transaction.rb +105 -105
  285. data/lib/rubydb/rails/type.rb +126 -126
  286. data/lib/rubydb/recovery/checkpoint.rb +261 -257
  287. data/lib/rubydb/recovery/consistency.rb +457 -467
  288. data/lib/rubydb/recovery/corruption_detector.rb +5 -5
  289. data/lib/rubydb/recovery/crash_recovery.rb +381 -387
  290. data/lib/rubydb/recovery/recovery_manager.rb +204 -206
  291. data/lib/rubydb/recovery/redo.rb +235 -237
  292. data/lib/rubydb/recovery/undo.rb +204 -206
  293. data/lib/rubydb/replication/failover.rb +5 -5
  294. data/lib/rubydb/replication/fencing.rb +63 -63
  295. data/lib/rubydb/replication/primary.rb +461 -450
  296. data/lib/rubydb/replication/replica.rb +382 -384
  297. data/lib/rubydb/replication/replication_log.rb +194 -200
  298. data/lib/rubydb/replication/replication_manager.rb +307 -308
  299. data/lib/rubydb/replication/replication_slot.rb +293 -295
  300. data/lib/rubydb/replication/replication_stream.rb +198 -201
  301. data/lib/rubydb/rubydb.rb +564 -560
  302. data/lib/rubydb/security/access_control.rb +252 -254
  303. data/lib/rubydb/security/audit_log.rb +209 -213
  304. data/lib/rubydb/security/authentication.rb +302 -302
  305. data/lib/rubydb/security/authorization.rb +282 -282
  306. data/lib/rubydb/security/credentials.rb +192 -196
  307. data/lib/rubydb/security/password.rb +205 -215
  308. data/lib/rubydb/security/permissions.rb +74 -74
  309. data/lib/rubydb/security/role.rb +99 -101
  310. data/lib/rubydb/security/user.rb +86 -86
  311. data/lib/rubydb/server/connection.rb +383 -366
  312. data/lib/rubydb/server/connection_pool.rb +193 -193
  313. data/lib/rubydb/server/lifecycle.rb +227 -228
  314. data/lib/rubydb/server/listener.rb +139 -136
  315. data/lib/rubydb/server/request_handler.rb +277 -276
  316. data/lib/rubydb/server/server.rb +363 -364
  317. data/lib/rubydb/server/session.rb +371 -369
  318. data/lib/rubydb/server/worker.rb +206 -210
  319. data/lib/rubydb/server/worker_pool.rb +168 -168
  320. data/lib/rubydb/sql/ast/alter_table.rb +169 -169
  321. data/lib/rubydb/sql/ast/begin_transaction.rb +47 -47
  322. data/lib/rubydb/sql/ast/commit.rb +37 -37
  323. data/lib/rubydb/sql/ast/constraint.rb +92 -83
  324. data/lib/rubydb/sql/ast/create_database.rb +41 -41
  325. data/lib/rubydb/sql/ast/create_index.rb +61 -61
  326. data/lib/rubydb/sql/ast/create_schema.rb +52 -52
  327. data/lib/rubydb/sql/ast/create_table.rb +187 -187
  328. data/lib/rubydb/sql/ast/delete.rb +54 -54
  329. data/lib/rubydb/sql/ast/drop_database.rb +41 -41
  330. data/lib/rubydb/sql/ast/drop_index.rb +41 -41
  331. data/lib/rubydb/sql/ast/drop_schema.rb +49 -49
  332. data/lib/rubydb/sql/ast/drop_table.rb +49 -49
  333. data/lib/rubydb/sql/ast/explain.rb +64 -64
  334. data/lib/rubydb/sql/ast/expression.rb +617 -604
  335. data/lib/rubydb/sql/ast/insert.rb +66 -66
  336. data/lib/rubydb/sql/ast/node.rb +42 -42
  337. data/lib/rubydb/sql/ast/rollback.rb +63 -63
  338. data/lib/rubydb/sql/ast/savepoint.rb +59 -59
  339. data/lib/rubydb/sql/ast/select.rb +88 -88
  340. data/lib/rubydb/sql/ast/set_operation.rb +22 -20
  341. data/lib/rubydb/sql/ast/trigger.rb +35 -29
  342. data/lib/rubydb/sql/ast/update.rb +88 -88
  343. data/lib/rubydb/sql/ast/vacuum.rb +19 -19
  344. data/lib/rubydb/sql/ast/view.rb +38 -32
  345. data/lib/rubydb/sql/ast/with.rb +32 -32
  346. data/lib/rubydb/sql/grammar.rb +86 -86
  347. data/lib/rubydb/sql/keywords.rb +156 -156
  348. data/lib/rubydb/sql/lexer.rb +209 -214
  349. data/lib/rubydb/sql/operators.rb +100 -100
  350. data/lib/rubydb/sql/parser.rb +1167 -1170
  351. data/lib/rubydb/sql/planner/analyzer.rb +283 -302
  352. data/lib/rubydb/sql/planner/binder.rb +537 -550
  353. data/lib/rubydb/sql/planner/type_checker.rb +427 -431
  354. data/lib/rubydb/sql/token.rb +210 -210
  355. data/lib/rubydb/storage/buffer_frame.rb +44 -44
  356. data/lib/rubydb/storage/buffer_pool.rb +155 -155
  357. data/lib/rubydb/storage/database_lock.rb +74 -74
  358. data/lib/rubydb/storage/deserializer.rb +332 -342
  359. data/lib/rubydb/storage/engine.rb +2347 -2330
  360. data/lib/rubydb/storage/file_manager.rb +191 -187
  361. data/lib/rubydb/storage/free_space_map.rb +79 -81
  362. data/lib/rubydb/storage/page.rb +92 -94
  363. data/lib/rubydb/storage/page_allocator.rb +852 -855
  364. data/lib/rubydb/storage/page_header.rb +63 -67
  365. data/lib/rubydb/storage/page_manager.rb +127 -131
  366. data/lib/rubydb/storage/record.rb +58 -58
  367. data/lib/rubydb/storage/row.rb +78 -78
  368. data/lib/rubydb/storage/serializer.rb +51 -51
  369. data/lib/rubydb/storage/storage_layout.rb +151 -151
  370. data/lib/rubydb/storage/storage_manager.rb +114 -114
  371. data/lib/rubydb/storage/tuple.rb +458 -461
  372. data/lib/rubydb/storage/visibility_map.rb +964 -973
  373. data/lib/rubydb/transactions/commit_manager.rb +219 -220
  374. data/lib/rubydb/transactions/isolation.rb +98 -98
  375. data/lib/rubydb/transactions/lock.rb +76 -76
  376. data/lib/rubydb/transactions/lock_manager.rb +359 -362
  377. data/lib/rubydb/transactions/savepoint.rb +142 -143
  378. data/lib/rubydb/transactions/transaction.rb +214 -215
  379. data/lib/rubydb/transactions/transaction_id.rb +84 -84
  380. data/lib/rubydb/transactions/transaction_log.rb +256 -257
  381. data/lib/rubydb/transactions/transaction_manager.rb +434 -435
  382. data/lib/rubydb/types/bigint.rb +36 -36
  383. data/lib/rubydb/types/blob.rb +37 -37
  384. data/lib/rubydb/types/boolean.rb +34 -34
  385. data/lib/rubydb/types/date.rb +39 -39
  386. data/lib/rubydb/types/decimal.rb +48 -48
  387. data/lib/rubydb/types/float.rb +34 -34
  388. data/lib/rubydb/types/integer.rb +36 -36
  389. data/lib/rubydb/types/json.rb +41 -41
  390. data/lib/rubydb/types/null.rb +34 -34
  391. data/lib/rubydb/types/smallint.rb +36 -36
  392. data/lib/rubydb/types/text.rb +37 -37
  393. data/lib/rubydb/types/time.rb +46 -46
  394. data/lib/rubydb/types/timestamp.rb +39 -39
  395. data/lib/rubydb/types/type.rb +119 -119
  396. data/lib/rubydb/types/uuid.rb +47 -47
  397. data/lib/rubydb/types/varchar.rb +37 -37
  398. data/lib/rubydb/version.rb +32 -32
  399. data/lib/rubydb/wal/archive.rb +190 -193
  400. data/lib/rubydb/wal/checkpoint.rb +181 -183
  401. data/lib/rubydb/wal/lsn.rb +94 -94
  402. data/lib/rubydb/wal/reader.rb +259 -260
  403. data/lib/rubydb/wal/record.rb +105 -105
  404. data/lib/rubydb/wal/segment.rb +193 -193
  405. data/lib/rubydb/wal/wal.rb +480 -452
  406. data/lib/rubydb/wal/writer.rb +236 -236
  407. data/lib/rubydb.rb +7 -7
  408. data/packaging/docker/docker-compose.failover.yml +43 -43
  409. data/packaging/homebrew/rubydb.rb +19 -19
  410. data/rubydb.gemspec +60 -57
  411. data/scripts/benchmark +7 -7
  412. data/scripts/durability_drill +37 -37
  413. data/scripts/fuzz +63 -63
  414. data/scripts/release +45 -40
  415. data/scripts/release_check +43 -43
  416. data/scripts/replication_failover_drill +268 -250
  417. data/scripts/replication_network_failover_drill +287 -255
  418. data/scripts/restore_drill +45 -45
  419. data/scripts/security +45 -0
  420. metadata +54 -1
@@ -0,0 +1,94 @@
1
+ # Lesson 7: a hybrid microservice architecture
2
+
3
+ A practical RubyDB architecture is to keep the large shared business system
4
+ on PostgreSQL and use RubyDB for a small service with a narrow responsibility.
5
+ Examples include a local catalog, a bounded document/index service, an
6
+ internal workflow, or a tenant-isolated tool whose SQL and recovery needs have
7
+ been validated.
8
+
9
+ ## Give each service ownership
10
+
11
+ ```text
12
+ Rails monolith / public API
13
+ |
14
+ +--> PostgreSQL: users, billing, orders, reporting
15
+ |
16
+ +--> RubyDB service API: bounded internal records
17
+ |
18
+ +--> one RubyDB server and persistent data directory
19
+ ```
20
+
21
+ The services communicate through an API or an event contract. They do not
22
+ share an embedded file and they do not write directly into each other’s tables.
23
+ Each service owns its migrations, credentials, backups, alerts, and recovery
24
+ runbook.
25
+
26
+ ## Ruby client for a service
27
+
28
+ ```ruby
29
+ # app/services/catalog_store.rb
30
+ require "rubydb"
31
+
32
+ class CatalogStore
33
+ def initialize(url: ENV.fetch("RUBYDB_URL"))
34
+ @client = RubyDB::Client::Client.new(url: url)
35
+ end
36
+
37
+ def find(code)
38
+ result = @client.query(
39
+ "SELECT code, title FROM catalog_items WHERE code = ?",
40
+ [code]
41
+ )
42
+ result.to_a.first
43
+ end
44
+
45
+ def close
46
+ @client.disconnect
47
+ end
48
+ end
49
+ ```
50
+
51
+ Use the actual client API in the version pinned by the service and add tests
52
+ for connection failures, timeouts, duplicate requests, and empty results. In a
53
+ long-running app, put client lifecycle management in the application’s
54
+ dependency/container layer and close it during shutdown.
55
+
56
+ ## A small Rails service
57
+
58
+ ```yaml
59
+ # service/config/database.yml
60
+ production:
61
+ adapter: rubydb
62
+ embedded: false
63
+ url: <%= ENV.fetch("RUBYDB_URL") %>
64
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
65
+ ```
66
+
67
+ Keep the API idempotent. A client timeout can happen after the server commits
68
+ a write, so a retry must use an idempotency key or first check the operation’s
69
+ result. For cross-service workflows, record an outbox/event in the owning
70
+ system and design consumers to tolerate duplicate delivery.
71
+
72
+ ## What belongs where
73
+
74
+ Keep users, payments, orders, and cross-tenant reporting in PostgreSQL when
75
+ they need shared relational consistency and broad analytical tooling. Keep
76
+ RubyDB data that can be independently backed up, restored, migrated, and
77
+ reconciled. Do not split a single atomic business transaction across the two
78
+ databases unless you have designed and tested a distributed workflow.
79
+
80
+ ## Failure and deployment rules
81
+
82
+ * Deploy the RubyDB service with a persistent volume and one server owner.
83
+ * Make the service private; clients use TLS and least-privilege credentials.
84
+ * Set bounded connection and request timeouts and expose a useful health probe.
85
+ * Retry only idempotent operations, with backoff and a maximum attempt count.
86
+ * Maintain a PostgreSQL and RubyDB restore drill independently.
87
+ * Version the API/event contract before changing either database schema.
88
+
89
+ ## Checkpoint
90
+
91
+ The checkpoint passes when each data set has one owner, the API can tolerate a
92
+ restarted database service, duplicate requests do not create duplicate business
93
+ records, and the two systems can be restored independently. Continue to [lesson 8](08-migrations-backups-recovery.md)
94
+ for migration and recovery drills.
@@ -0,0 +1,86 @@
1
+ # Lesson 8: migrations, backups, and recovery
2
+
3
+ Production data work is a controlled change to a recoverable system. A green
4
+ migration on an empty database is not enough. Test populated tables, rollback
5
+ boundaries, disk growth, indexes, locks, and application compatibility.
6
+
7
+ ## RubyDB migration workflow
8
+
9
+ Preview and apply a migration against a disposable or staging copy:
10
+
11
+ ```sh
12
+ rubydb doctor --quick --json
13
+ rubydb backup --database data/app.rdb --dir backups --type full --compress
14
+ rubydb migrate --database data/app.rdb --path db/migrate --dry-run
15
+ rubydb migrate --database data/app.rdb --path db/migrate
16
+ ```
17
+
18
+ Run the migration once from a release job, not once per web process. Keep the
19
+ pre-migration backup and record the database version, application revision,
20
+ backup checksum, operator, and start/end times.
21
+
22
+ ## Verified RubyDB backup and restore
23
+
24
+ Create a full backup with verification enabled, then dry-run the restore:
25
+
26
+ ```sh
27
+ rubydb backup --database data/app.rdb --dir backups --type full --compress
28
+ rubydb restore --dir backups --latest --dry-run
29
+ rubydb restore --database restored/app.rdb --dir backups --latest
30
+ ```
31
+
32
+ If a release depends on incremental or differential backups, retain the entire
33
+ required chain and its manifest. Keep backups away from the database disk and
34
+ test that a new host can read them. Restore into a new inactive path; do not
35
+ overwrite the only source with `--force`.
36
+
37
+ After restoring, verify both structure and meaning:
38
+
39
+ ```sh
40
+ rubydb inspect --database restored/app.rdb --stats --wal
41
+ rubydb shell --database restored/app.rdb --json
42
+ ```
43
+
44
+ Run schema checks, row counts, foreign-key checks, representative application
45
+ queries, and business totals. Record the achieved RPO and RTO rather than
46
+ assuming the command’s success proves recoverability.
47
+
48
+ ## PostgreSQL backup and restore
49
+
50
+ For PostgreSQL, use the provider’s managed backup/PITR feature where possible
51
+ and rehearse an independent logical backup:
52
+
53
+ ```sh
54
+ pg_dump --format=custom --file=tmp/app-staging.dump "$DATABASE_URL"
55
+ createdb app_restore
56
+ pg_restore --clean --if-exists --dbname=app_restore tmp/app-staging.dump
57
+ ```
58
+
59
+ The restore target must be isolated from production. Validate extensions,
60
+ roles, ownership, sequences, indexes, and application behavior after restore.
61
+ For a managed service, follow its documented restore and point-in-time
62
+ procedure instead of assuming local `createdb` access exists.
63
+
64
+ ## Corruption and interrupted writes
65
+
66
+ When storage or recovery is suspect:
67
+
68
+ 1. stop application writes and preserve the database, WAL, metadata, config,
69
+ and logs together;
70
+ 2. copy the evidence to a separate incident location;
71
+ 3. run `doctor --quick` and `inspect --stats --wal` on the copy;
72
+ 4. restore the latest verified backup into a new path;
73
+ 5. compare schema, row counts, checksums, and business totals; and
74
+ 6. document what data was lost, replayed, or manually reconciled.
75
+
76
+ Do not “repair” corruption by deleting files, dropping tables, or running full
77
+ vacuum on the only copy. Use the repository’s durability and recovery drills
78
+ to rehearse interrupted checkpoints, full disks, corrupted files, compaction,
79
+ and restore at scale before an incident.
80
+
81
+ ## Checkpoint
82
+
83
+ The checkpoint passes when an operator who did not create the backup can restore
84
+ it on another path, prove the data is usable, and state measured RPO/RTO. Keep
85
+ the report with the release evidence. Continue to [lesson 9](09-observability-security-scale.md)
86
+ for operations and security.
@@ -0,0 +1,87 @@
1
+ # Lesson 9: observability, security, and scale
2
+
3
+ Production readiness is an operating discipline. A database is ready only when
4
+ the team can see failures, limit damage, rotate credentials, and make a safe
5
+ recovery decision under pressure.
6
+
7
+ ## Protect the connection
8
+
9
+ For RubyDB server mode, use a private network, password authentication, and
10
+ TLS with peer verification:
11
+
12
+ ```text
13
+ rubydbs://app_user:URL_ENCODED_PASSWORD@db.internal.example:7432/app?verify_peer=true&ca_file=%2Fetc%2Frubydb%2Fca.crt
14
+ ```
15
+
16
+ Store `RUBYDB_URL`, `RUBYDB_PASSWORD`, certificates, and private keys in the
17
+ deployment secret manager. Do not commit them, put them in a Docker image, or
18
+ print them in health checks. Give the application only the database privileges
19
+ it needs and use a separate migration/admin identity.
20
+
21
+ For PostgreSQL, use `DATABASE_URL` from the provider’s secret store, TLS
22
+ settings required by that provider, least-privilege roles, and rotated
23
+ credentials. Review role grants after every schema or service change.
24
+
25
+ ## Set limits before load
26
+
27
+ Bound every layer that can wait:
28
+
29
+ ```yaml
30
+ # config/database.yml
31
+ production:
32
+ adapter: rubydb
33
+ embedded: false
34
+ url: <%= ENV.fetch("RUBYDB_URL") %>
35
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
36
+ checkout_timeout: <%= ENV.fetch("DB_CHECKOUT_TIMEOUT", "5") %>
37
+ ```
38
+
39
+ Also set application request/job timeouts, connection idle limits, server
40
+ connection limits, maximum request body sizes, and process memory/CPU limits.
41
+ Choose values from measurements. A timeout should fail a request cleanly and
42
+ produce a useful event; it should not cause an unsafe blind retry.
43
+
44
+ ## Monitor signals that lead to incidents
45
+
46
+ Collect metrics and structured logs for:
47
+
48
+ * request and query latency by operation, including p95 and p99;
49
+ * error, timeout, cancellation, retry, and deadlock counts;
50
+ * active connections, pool wait time, and transaction age;
51
+ * WAL/checkpoint growth, database size, free disk, and compaction/vacuum time;
52
+ * backup age, backup verification result, restore drill age, and RPO/RTO; and
53
+ * process restarts, readiness failures, replication lag, and failover events.
54
+
55
+ The RubyDB CLI is useful evidence in an operator check:
56
+
57
+ ```sh
58
+ rubydb --env production status --json
59
+ rubydb --env production doctor --quick --json
60
+ rubydb inspect --database data/app.rdb --stats --wal
61
+ ```
62
+
63
+ Turn those outputs into alerts with thresholds and an owner. A green process
64
+ status is not the same as a healthy application: include a real application
65
+ query and a write/read smoke test in staging and deployment verification.
66
+
67
+ ## Load and concurrency validation
68
+
69
+ Start with a reproducible workload, then increase concurrency gradually:
70
+
71
+ ```sh
72
+ RUBYDB_WORKLOAD_THREADS=16 RUBYDB_WORKLOAD_OPERATIONS=10000 \
73
+ ruby benchmarks/concurrent_workload.rb
74
+ ```
75
+
76
+ Use the repository’s documented workload script and record its output. Measure
77
+ throughput, latency, failures, cancellations, timeouts, deadlocks, memory, WAL,
78
+ and disk use. Run long enough to expose leaks and queue growth. Test separate
79
+ processes and separate hosts for server mode; an in-process benchmark does not
80
+ prove network behavior.
81
+
82
+ ## Checkpoint
83
+
84
+ The checkpoint passes when alerts have thresholds and owners, secrets can be
85
+ rotated without source changes, resource limits are documented, and a sustained
86
+ test produces a baseline with no unexplained errors or unbounded growth.
87
+ Continue to [lesson 10](10-release-readiness.md) for the release gate.
@@ -0,0 +1,125 @@
1
+ # Lesson 10: release readiness
2
+
3
+ The final checkpoint is evidence, not optimism. A production release should
4
+ identify the exact RubyDB and adapter versions, supported Ruby/Rails/OS matrix,
5
+ tested SQL surface, backup artifact, restore result, load baseline, security
6
+ review, and rollback owner.
7
+
8
+ ## Run repository checks
9
+
10
+ From the RubyDB repository:
11
+
12
+ ```sh
13
+ bundle install
14
+ bundle exec rspec
15
+ bundle exec rake
16
+ git diff --check
17
+ ```
18
+
19
+ Run the Rails adapter suite from its directory and repeat it for every Rails
20
+ and Ruby version you claim to support:
21
+
22
+ ```sh
23
+ cd adapters/activerecord
24
+ bundle install
25
+ bundle exec rspec
26
+ ```
27
+
28
+ Add your application’s complex query, migration, schema dump/load, concurrency,
29
+ and failure tests to CI. A passing library suite does not certify an arbitrary
30
+ application.
31
+
32
+ ## Release a gem safely
33
+
34
+ Review the project’s release instructions and run the preflight with a version
35
+ that has not already been published:
36
+
37
+ ```sh
38
+ RUBYDB_RELEASE_VERSION=0.1.5 ruby scripts/release
39
+ ```
40
+
41
+ On PowerShell, use:
42
+
43
+ ```powershell
44
+ $env:RUBYDB_RELEASE_VERSION = "0.1.5"
45
+ ruby scripts/release
46
+ ```
47
+
48
+ The release script builds the gem and writes a checksum. Check the artifact
49
+ locally before publishing:
50
+
51
+ ```sh
52
+ gem specification pkg/rubydb-0.1.5.gem
53
+ gem install pkg/rubydb-0.1.5.gem --local
54
+ ruby -rrubydb -e 'puts RubyDB::VERSION'
55
+ ```
56
+
57
+ Publishing requires a RubyGems API key or trusted publishing setup configured
58
+ on the release machine. The local script publishes only when both the explicit
59
+ publish flag and secret are present; never commit the secret:
60
+
61
+ ```sh
62
+ RUBYDB_RELEASE_VERSION=0.1.5 \
63
+ RUBYDB_PUBLISH=1 \
64
+ GEM_HOST_API_KEY="YOUR_RUBYGEMS_API_KEY" \
65
+ ruby scripts/release
66
+ ```
67
+
68
+ On Windows PowerShell:
69
+
70
+ ```powershell
71
+ $env:RUBYDB_RELEASE_VERSION = "0.1.5"
72
+ $env:RUBYDB_PUBLISH = "1"
73
+ $env:GEM_HOST_API_KEY = "YOUR_RUBYGEMS_API_KEY"
74
+ ruby scripts/release
75
+ ```
76
+
77
+ Prefer the repository’s signed GitHub Actions release workflow for a public
78
+ release. Store signing keys and RubyGems secrets only in protected secret
79
+ storage; do not put them in the repository or a checked-in `.env` file.
80
+
81
+ Release the adapter separately when its version changes, update the changelog,
82
+ tag the source commit, and publish the checksums and supported-version notes.
83
+
84
+ ## Deployment gate
85
+
86
+ For a direct RubyDB production deployment, follow [lesson 5](05-rubydb-production-server.md)
87
+ from top to bottom before this gate. For a massive Rails application, follow
88
+ [lesson 6](06-postgresql-massive-apps.md) and keep RubyDB at a separate service
89
+ boundary.
90
+
91
+ Do not promote until all of these have an owner and a recorded result:
92
+
93
+ * application tests pass against the production database topology;
94
+ * migrations pass on empty and populated staging data;
95
+ * a verified backup restores on another path or host;
96
+ * load tests cover concurrency, timeouts, cancellation, and resource limits;
97
+ * multi-process client/server tests cover restart and network failure;
98
+ * failover and fencing behavior is validated if high availability is claimed;
99
+ * TLS, secrets, least privilege, certificate rotation, and audit logging are
100
+ reviewed;
101
+ * dashboards and alerts page an on-call person;
102
+ * rollback, upgrade, and data-reconciliation procedures are rehearsed; and
103
+ * the README and compatibility guide state what is supported and what is not.
104
+
105
+ ## A sensible first production architecture
106
+
107
+ For a large Rails product, use managed PostgreSQL for the main application and
108
+ deploy RubyDB only for an independently owned microservice whose workload has
109
+ passed the lessons above. For a small internal or single-owner service, RubyDB
110
+ server mode can be reasonable when its SQL, concurrency, recovery, and
111
+ operational limits are accepted. Do not call either architecture universally
112
+ compatible without workload evidence.
113
+
114
+ ## Final checkpoint
115
+
116
+ The journey is complete when a new operator can deploy the exact release,
117
+ verify a real query, observe health and capacity, restore data, and explain the
118
+ rollback path without relying on the author’s laptop. Keep the evidence with
119
+ the release and repeat the drills after major RubyDB, Rails, schema, or hosting
120
+ changes.
121
+
122
+ Continue using the repository’s [CLI guide](../docs/cli.md), [production
123
+ operations guide](../docs/operations/production-guide.md), [Rails compatibility
124
+ guide](../docs/rails/compatibility-guide.md), and [SQL compatibility
125
+ guide](../docs/sql/compatibility-guide.md) as the detailed references.