rubydb 0.1.4 → 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 +43 -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 +873 -879
  30. data/adapters/activerecord/rubydb-activerecord.gemspec +20 -20
  31. data/adapters/activerecord/spec/rubydb_adapter_integration_spec.rb +143 -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 +1182 -1188
  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 +117 -117
  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
@@ -1,244 +1,244 @@
1
- # RubyDB troubleshooting guide
2
-
3
- This guide is for developers and operators diagnosing a live or test
4
- deployment. Preserve evidence before attempting recovery. If data is
5
- important, stop writes, copy the database directory and WAL to protected
6
- storage, record the RubyDB version and commit, and work on a copy.
7
-
8
- ## First response
9
-
10
- Collect the smallest useful incident bundle:
11
-
12
- ```sh
13
- ruby -v
14
- bundle exec ruby -Ilib exe/rubydb --version
15
- bundle exec ruby -Ilib exe/rubydb status --config config/rubydb.yml
16
- bundle exec ruby -Ilib exe/rubydb doctor --config config/rubydb.yml
17
- ```
18
-
19
- Also record the operating system, deployment topology, database path (without
20
- credentials), configuration checksum, recent migrations, request IDs, error
21
- logs, disk/free-inode state, process list, and whether the failure affects
22
- embedded mode, server mode, or both. Redact passwords, tokens, private keys,
23
- certificate contents, and customer values.
24
-
25
- Do not delete WAL files, run vacuum, force promotion, or retry an unknown
26
- commit until the state and evidence are preserved.
27
-
28
- ## Startup and configuration
29
-
30
- ### The database will not open
31
-
32
- Check that the path is the intended directory, is readable and writable by the
33
- service account, and is not already owned by another embedded process. Inspect
34
- the status and doctor output. If the path contains an incomplete checkpoint,
35
- use the documented recovery flow and keep the original directory unchanged.
36
-
37
- Common causes are a wrong working directory, a missing parent directory,
38
- permissions, a stale lock, an unsupported format version, and an incomplete
39
- restore. A stale lock must be investigated against the process owner; never
40
- remove it merely because startup is inconvenient.
41
-
42
- ### The server starts and immediately exits
43
-
44
- Run the same command in the foreground with verbose logging. Validate the
45
- configuration, TLS files, certificate/key pairing, authentication settings,
46
- listen address, and port availability. Check the service manager’s stdout and
47
- stderr rather than only its health endpoint. `RUBYDB_DEBUG=1` can expose a
48
- development backtrace; do not enable verbose debug output on a public service
49
- without reviewing sensitive data exposure.
50
-
51
- ### The server is healthy but clients cannot connect
52
-
53
- Confirm the client endpoint, port, TLS mode, CA path, SNI/hostname, and
54
- authentication credentials. Test from the same network namespace as the
55
- application. A listening socket proves only that a process has bound a port;
56
- the readiness check must also verify the database owner and request path.
57
-
58
- ## SQL and query failures
59
-
60
- ### A statement is rejected
61
-
62
- Capture the exact SQL shape with values redacted and determine whether the
63
- failure is parser, binder, planner, executor, or constraint related. Compare
64
- the statement against [SQL compatibility](sql/compatibility.md) and the
65
- [SQLite-style profile](sql/sqlite-compatibility.md). Test a minimal statement
66
- with one table, then add joins, predicates, grouping, and constraints one at a
67
- time.
68
-
69
- Do not assume that syntax accepted by SQLite, PostgreSQL, or MySQL has the
70
- same semantics in RubyDB. Unsupported dialect features should be rewritten or
71
- tracked as compatibility work, not hidden behind a generic fallback.
72
-
73
- ### Results are wrong or unstable
74
-
75
- Reproduce without the optimizer if that diagnostic mode exists, then compare
76
- the plan and row versions. Add explicit ordering when order is part of the
77
- application contract. Check `NULL` predicates, implicit casts, duplicate join
78
- keys, grouping columns, transaction snapshot, and stale statistics. Preserve
79
- the schema, seed data, SQL, and expected result as a regression spec.
80
-
81
- ### A query is slow
82
-
83
- Record query shape, row count, indexes, bind values, plan, duration, lock wait,
84
- and whether the delay is execution or checkpoint/WAL pressure. Test with and
85
- without the suspected index and inspect the scan cardinality. Do not add
86
- indexes blindly: each index adds write, storage, recovery, and vacuum cost.
87
-
88
- ## Transactions, locks, and concurrency
89
-
90
- ### Requests hang
91
-
92
- Separate network wait, lock wait, disk wait, and executor work. Check active
93
- transactions, lock owners, waiters, deadlines, and cancellation logs. Set a
94
- bounded request/lock timeout in staging and capture a thread dump. A timeout
95
- must release resources and report whether commit was known.
96
-
97
- ### Deadlock detected
98
-
99
- Keep the deadlock graph, victim transaction ID, SQL fingerprints, and lock
100
- order. Confirm that the victim rolled back all writes and released every lock.
101
- Retry only idempotent application work. Fix the application’s lock ordering or
102
- transaction size; do not disable deadlock detection.
103
-
104
- ### Data disappears inside a transaction
105
-
106
- Check snapshot timing, savepoints, rollback paths, and whether the read and
107
- write use the same connection. In server mode, a transaction is connection
108
- scoped unless the API says otherwise. A connection-pool checkout must not
109
- reuse a connection with an open transaction.
110
-
111
- ### High concurrency causes errors
112
-
113
- Reduce workers and payload size, then increase one at a time. Monitor memory,
114
- file descriptors, WAL growth, checkpoint time, lock waits, cancellation rate,
115
- and p99 latency. Embedded mode has one process owner; use server mode for
116
- multiple application processes. Use the production soak scripts before
117
- changing limits.
118
-
119
- ## WAL, recovery, and corruption
120
-
121
- ### Recovery takes too long
122
-
123
- Measure WAL size, last checkpoint LSN, frame count, page count, and storage
124
- latency. A large WAL may indicate a blocked checkpoint, a long reader, or
125
- insufficient checkpoint scheduling. Preserve the directory, then run a copy
126
- through inspection and compaction. Never truncate WAL by hand.
127
-
128
- ### Checksum or framing validation fails
129
-
130
- Treat this as a durability incident. Stop writes, preserve all database and WAL
131
- files, capture filesystem and process termination evidence, and attempt restore
132
- from the newest verified backup in a separate directory. Compare checksums and
133
- LSNs. If the backup also fails, escalate with the complete evidence bundle.
134
-
135
- ### An index is inconsistent
136
-
137
- Do not make application decisions from a suspect index. Run the supported
138
- inspection/recovery or rebuild operation on a copy, compare indexed and table
139
- scans, and verify after reopen. The repair result must be durable before the
140
- copy is promoted. A failed index persistence operation must remain visible as
141
- an error.
142
-
143
- ### Disk is full
144
-
145
- Stop growth safely: pause writes if necessary, preserve logs, and identify
146
- database, WAL, backup, and temporary-file usage. Free capacity through the
147
- host’s approved procedure, then verify the filesystem and resume with a
148
- controlled write. Do not delete WAL, active checkpoints, or the newest backup
149
- to make room.
150
-
151
- ## Backup, restore, and upgrades
152
-
153
- ### Backup succeeds but restore fails
154
-
155
- Check the backup manifest, checksum, base identity, LSN range, compression,
156
- RubyDB version, and free space in the target directory. Restore to a fresh
157
- directory and run integrity, schema, row-count, and application smoke checks.
158
- Keep the failed restore for diagnosis.
159
-
160
- ### Incremental/differential chain is rejected
161
-
162
- Restore the verified base first and apply deltas in order. Confirm that the
163
- declared base checksum and LSN match. Missing or reordered pieces must fail
164
- closed; do not bypass validation.
165
-
166
- ### An upgrade will not start
167
-
168
- Read the upgrade guard and format version. Take a verified backup, test the
169
- upgrade on a copy with a representative workload, and retain a rollback plan.
170
- Do not mix binary versions against a live embedded directory unless the
171
- compatibility contract explicitly allows it.
172
-
173
- ## Replication and failover
174
-
175
- ### Replica is behind
176
-
177
- Compare primary and replica acknowledged LSN, WAL retention, connection state,
178
- authentication, and apply errors. Check that the replica is not accepting
179
- writes. Reconnect/catch up through the supported protocol and verify row and
180
- LSN consistency before promotion.
181
-
182
- ### Promotion is rejected
183
-
184
- Promotion should require a synchronized candidate and a valid fencing epoch.
185
- Resolve lag, stale metadata, or fence ownership first. Never force promotion
186
- because an application health check is red; a stale primary may still be able
187
- to write.
188
-
189
- ### Suspected split brain
190
-
191
- Fence both writers at the deployment layer, stop application writes, preserve
192
- both logs and WALs, and identify the highest acknowledged commit/fence epoch.
193
- Do not merge divergent database directories manually. The current RubyDB
194
- workflow is explicitly fenced/manual unless a deployment has separately
195
- validated its election and fencing system across hosts.
196
-
197
- ## Rails and migrations
198
-
199
- Check the Rails/Ruby versions, adapter configuration, connection pool size,
200
- database ownership mode, generated SQL, bind values, and migration version.
201
- Run `db:migrate:status`, inspect schema state, and compare the schema dump with
202
- the intended model. For a populated-table migration, test on a copy and plan
203
- backfill, locking, rollback, and deployment sequencing.
204
-
205
- Frequent causes include unsupported generated SQL, an embedded path shared by
206
- web and job processes, pool size exceeding server capacity, a migration
207
- checksum mismatch, or a schema dump that uses a feature outside RubyDB’s
208
- documented profile. See [Rails compatibility](rails/compatibility-guide.md)
209
- and [Rails troubleshooting](rails/troubleshooting.md).
210
-
211
- ## TLS, authentication, and authorization
212
-
213
- Verify the server certificate chain, hostname, expiration, key permissions,
214
- CA bundle, and client/server TLS settings. Rotate certificates by staging the
215
- new chain, testing a client, switching atomically, and retaining the old chain
216
- only for the documented overlap period. Rotate secrets through the secret
217
- manager, not source control or command-line history.
218
-
219
- Authentication success does not imply authorization. Check the authenticated
220
- identity, role, operation, database, and audit record. Treat repeated failures
221
- as a security event and preserve timestamps and request IDs.
222
-
223
- ## Resource exhaustion
224
-
225
- Track open files, memory, threads, CPU, disk bytes, inodes, WAL size, active
226
- transactions, pool utilization, and queue depth. Apply limits at the service
227
- and application layers. Reduce concurrency before raising limits, and confirm
228
- that cancellation and shutdown drain work without corrupting state.
229
-
230
- ## Evidence and escalation
231
-
232
- An actionable report includes:
233
-
234
- * exact command/API and a minimal reproduction;
235
- * RubyDB commit/version, Ruby/Rails versions, OS and filesystem;
236
- * topology, configuration names, and relevant metrics;
237
- * sanitized logs with request/transaction/LSN identifiers;
238
- * database/WAL/backup checksums and sizes;
239
- * expected versus actual result; and
240
- * what was already attempted and whether it changed state.
241
-
242
- See [Debugging RubyDB](debugging.md) for collection commands and safe
243
- instrumentation.
244
-
1
+ # RubyDB troubleshooting guide
2
+
3
+ This guide is for developers and operators diagnosing a live or test
4
+ deployment. Preserve evidence before attempting recovery. If data is
5
+ important, stop writes, copy the database directory and WAL to protected
6
+ storage, record the RubyDB version and commit, and work on a copy.
7
+
8
+ ## First response
9
+
10
+ Collect the smallest useful incident bundle:
11
+
12
+ ```sh
13
+ ruby -v
14
+ bundle exec ruby -Ilib exe/rubydb --version
15
+ bundle exec ruby -Ilib exe/rubydb status --config config/rubydb.yml
16
+ bundle exec ruby -Ilib exe/rubydb doctor --config config/rubydb.yml
17
+ ```
18
+
19
+ Also record the operating system, deployment topology, database path (without
20
+ credentials), configuration checksum, recent migrations, request IDs, error
21
+ logs, disk/free-inode state, process list, and whether the failure affects
22
+ embedded mode, server mode, or both. Redact passwords, tokens, private keys,
23
+ certificate contents, and customer values.
24
+
25
+ Do not delete WAL files, run vacuum, force promotion, or retry an unknown
26
+ commit until the state and evidence are preserved.
27
+
28
+ ## Startup and configuration
29
+
30
+ ### The database will not open
31
+
32
+ Check that the path is the intended directory, is readable and writable by the
33
+ service account, and is not already owned by another embedded process. Inspect
34
+ the status and doctor output. If the path contains an incomplete checkpoint,
35
+ use the documented recovery flow and keep the original directory unchanged.
36
+
37
+ Common causes are a wrong working directory, a missing parent directory,
38
+ permissions, a stale lock, an unsupported format version, and an incomplete
39
+ restore. A stale lock must be investigated against the process owner; never
40
+ remove it merely because startup is inconvenient.
41
+
42
+ ### The server starts and immediately exits
43
+
44
+ Run the same command in the foreground with verbose logging. Validate the
45
+ configuration, TLS files, certificate/key pairing, authentication settings,
46
+ listen address, and port availability. Check the service manager’s stdout and
47
+ stderr rather than only its health endpoint. `RUBYDB_DEBUG=1` can expose a
48
+ development backtrace; do not enable verbose debug output on a public service
49
+ without reviewing sensitive data exposure.
50
+
51
+ ### The server is healthy but clients cannot connect
52
+
53
+ Confirm the client endpoint, port, TLS mode, CA path, SNI/hostname, and
54
+ authentication credentials. Test from the same network namespace as the
55
+ application. A listening socket proves only that a process has bound a port;
56
+ the readiness check must also verify the database owner and request path.
57
+
58
+ ## SQL and query failures
59
+
60
+ ### A statement is rejected
61
+
62
+ Capture the exact SQL shape with values redacted and determine whether the
63
+ failure is parser, binder, planner, executor, or constraint related. Compare
64
+ the statement against [SQL compatibility](sql/compatibility.md) and the
65
+ [SQLite-style profile](sql/sqlite-compatibility.md). Test a minimal statement
66
+ with one table, then add joins, predicates, grouping, and constraints one at a
67
+ time.
68
+
69
+ Do not assume that syntax accepted by SQLite, PostgreSQL, or MySQL has the
70
+ same semantics in RubyDB. Unsupported dialect features should be rewritten or
71
+ tracked as compatibility work, not hidden behind a generic fallback.
72
+
73
+ ### Results are wrong or unstable
74
+
75
+ Reproduce without the optimizer if that diagnostic mode exists, then compare
76
+ the plan and row versions. Add explicit ordering when order is part of the
77
+ application contract. Check `NULL` predicates, implicit casts, duplicate join
78
+ keys, grouping columns, transaction snapshot, and stale statistics. Preserve
79
+ the schema, seed data, SQL, and expected result as a regression spec.
80
+
81
+ ### A query is slow
82
+
83
+ Record query shape, row count, indexes, bind values, plan, duration, lock wait,
84
+ and whether the delay is execution or checkpoint/WAL pressure. Test with and
85
+ without the suspected index and inspect the scan cardinality. Do not add
86
+ indexes blindly: each index adds write, storage, recovery, and vacuum cost.
87
+
88
+ ## Transactions, locks, and concurrency
89
+
90
+ ### Requests hang
91
+
92
+ Separate network wait, lock wait, disk wait, and executor work. Check active
93
+ transactions, lock owners, waiters, deadlines, and cancellation logs. Set a
94
+ bounded request/lock timeout in staging and capture a thread dump. A timeout
95
+ must release resources and report whether commit was known.
96
+
97
+ ### Deadlock detected
98
+
99
+ Keep the deadlock graph, victim transaction ID, SQL fingerprints, and lock
100
+ order. Confirm that the victim rolled back all writes and released every lock.
101
+ Retry only idempotent application work. Fix the application’s lock ordering or
102
+ transaction size; do not disable deadlock detection.
103
+
104
+ ### Data disappears inside a transaction
105
+
106
+ Check snapshot timing, savepoints, rollback paths, and whether the read and
107
+ write use the same connection. In server mode, a transaction is connection
108
+ scoped unless the API says otherwise. A connection-pool checkout must not
109
+ reuse a connection with an open transaction.
110
+
111
+ ### High concurrency causes errors
112
+
113
+ Reduce workers and payload size, then increase one at a time. Monitor memory,
114
+ file descriptors, WAL growth, checkpoint time, lock waits, cancellation rate,
115
+ and p99 latency. Embedded mode has one process owner; use server mode for
116
+ multiple application processes. Use the production soak scripts before
117
+ changing limits.
118
+
119
+ ## WAL, recovery, and corruption
120
+
121
+ ### Recovery takes too long
122
+
123
+ Measure WAL size, last checkpoint LSN, frame count, page count, and storage
124
+ latency. A large WAL may indicate a blocked checkpoint, a long reader, or
125
+ insufficient checkpoint scheduling. Preserve the directory, then run a copy
126
+ through inspection and compaction. Never truncate WAL by hand.
127
+
128
+ ### Checksum or framing validation fails
129
+
130
+ Treat this as a durability incident. Stop writes, preserve all database and WAL
131
+ files, capture filesystem and process termination evidence, and attempt restore
132
+ from the newest verified backup in a separate directory. Compare checksums and
133
+ LSNs. If the backup also fails, escalate with the complete evidence bundle.
134
+
135
+ ### An index is inconsistent
136
+
137
+ Do not make application decisions from a suspect index. Run the supported
138
+ inspection/recovery or rebuild operation on a copy, compare indexed and table
139
+ scans, and verify after reopen. The repair result must be durable before the
140
+ copy is promoted. A failed index persistence operation must remain visible as
141
+ an error.
142
+
143
+ ### Disk is full
144
+
145
+ Stop growth safely: pause writes if necessary, preserve logs, and identify
146
+ database, WAL, backup, and temporary-file usage. Free capacity through the
147
+ host’s approved procedure, then verify the filesystem and resume with a
148
+ controlled write. Do not delete WAL, active checkpoints, or the newest backup
149
+ to make room.
150
+
151
+ ## Backup, restore, and upgrades
152
+
153
+ ### Backup succeeds but restore fails
154
+
155
+ Check the backup manifest, checksum, base identity, LSN range, compression,
156
+ RubyDB version, and free space in the target directory. Restore to a fresh
157
+ directory and run integrity, schema, row-count, and application smoke checks.
158
+ Keep the failed restore for diagnosis.
159
+
160
+ ### Incremental/differential chain is rejected
161
+
162
+ Restore the verified base first and apply deltas in order. Confirm that the
163
+ declared base checksum and LSN match. Missing or reordered pieces must fail
164
+ closed; do not bypass validation.
165
+
166
+ ### An upgrade will not start
167
+
168
+ Read the upgrade guard and format version. Take a verified backup, test the
169
+ upgrade on a copy with a representative workload, and retain a rollback plan.
170
+ Do not mix binary versions against a live embedded directory unless the
171
+ compatibility contract explicitly allows it.
172
+
173
+ ## Replication and failover
174
+
175
+ ### Replica is behind
176
+
177
+ Compare primary and replica acknowledged LSN, WAL retention, connection state,
178
+ authentication, and apply errors. Check that the replica is not accepting
179
+ writes. Reconnect/catch up through the supported protocol and verify row and
180
+ LSN consistency before promotion.
181
+
182
+ ### Promotion is rejected
183
+
184
+ Promotion should require a synchronized candidate and a valid fencing epoch.
185
+ Resolve lag, stale metadata, or fence ownership first. Never force promotion
186
+ because an application health check is red; a stale primary may still be able
187
+ to write.
188
+
189
+ ### Suspected split brain
190
+
191
+ Fence both writers at the deployment layer, stop application writes, preserve
192
+ both logs and WALs, and identify the highest acknowledged commit/fence epoch.
193
+ Do not merge divergent database directories manually. The current RubyDB
194
+ workflow is explicitly fenced/manual unless a deployment has separately
195
+ validated its election and fencing system across hosts.
196
+
197
+ ## Rails and migrations
198
+
199
+ Check the Rails/Ruby versions, adapter configuration, connection pool size,
200
+ database ownership mode, generated SQL, bind values, and migration version.
201
+ Run `db:migrate:status`, inspect schema state, and compare the schema dump with
202
+ the intended model. For a populated-table migration, test on a copy and plan
203
+ backfill, locking, rollback, and deployment sequencing.
204
+
205
+ Frequent causes include unsupported generated SQL, an embedded path shared by
206
+ web and job processes, pool size exceeding server capacity, a migration
207
+ checksum mismatch, or a schema dump that uses a feature outside RubyDB’s
208
+ documented profile. See [Rails compatibility](rails/compatibility-guide.md)
209
+ and [Rails troubleshooting](rails/troubleshooting.md).
210
+
211
+ ## TLS, authentication, and authorization
212
+
213
+ Verify the server certificate chain, hostname, expiration, key permissions,
214
+ CA bundle, and client/server TLS settings. Rotate certificates by staging the
215
+ new chain, testing a client, switching atomically, and retaining the old chain
216
+ only for the documented overlap period. Rotate secrets through the secret
217
+ manager, not source control or command-line history.
218
+
219
+ Authentication success does not imply authorization. Check the authenticated
220
+ identity, role, operation, database, and audit record. Treat repeated failures
221
+ as a security event and preserve timestamps and request IDs.
222
+
223
+ ## Resource exhaustion
224
+
225
+ Track open files, memory, threads, CPU, disk bytes, inodes, WAL size, active
226
+ transactions, pool utilization, and queue depth. Apply limits at the service
227
+ and application layers. Reduce concurrency before raising limits, and confirm
228
+ that cancellation and shutdown drain work without corrupting state.
229
+
230
+ ## Evidence and escalation
231
+
232
+ An actionable report includes:
233
+
234
+ * exact command/API and a minimal reproduction;
235
+ * RubyDB commit/version, Ruby/Rails versions, OS and filesystem;
236
+ * topology, configuration names, and relevant metrics;
237
+ * sanitized logs with request/transaction/LSN identifiers;
238
+ * database/WAL/backup checksums and sizes;
239
+ * expected versus actual result; and
240
+ * what was already attempted and whether it changed state.
241
+
242
+ See [Debugging RubyDB](debugging.md) for collection commands and safe
243
+ instrumentation.
244
+
@@ -0,0 +1,73 @@
1
+ # RubyDB production journey
2
+
3
+ This ten-lesson journey teaches a practical way to use RubyDB without
4
+ pretending it is a universal PostgreSQL replacement. It is written for a
5
+ newcomer who wants copy-and-paste commands, but it ends with the operational
6
+ habits expected of a production team.
7
+
8
+ ## The decision in one picture
9
+
10
+ ```text
11
+ Browser / API clients
12
+ |
13
+ Rails app --------------------> PostgreSQL
14
+ | system of record for a large app
15
+ |
16
+ +---------------------------> RubyDB server
17
+ bounded internal microservice
18
+
19
+ RubyDB embedded = one owning Ruby process and one local persistent path.
20
+ ```
21
+
22
+ Use PostgreSQL when the application needs a broadly supported shared database,
23
+ many application instances, managed high availability, large connection and
24
+ query ecosystems, or PostgreSQL-specific SQL and extensions. Use RubyDB
25
+ embedded for local development, tests, tools, and a deliberately single-owner
26
+ workload. Use RubyDB server/client for a bounded service whose workload fits
27
+ RubyDB's documented SQL and operational surface.
28
+
29
+ RubyDB is currently alpha software. This guide is a deployment and learning
30
+ path, not a certification that every Rails query, SQL dialect feature, or
31
+ failure mode is supported. Test the exact application and keep PostgreSQL as
32
+ the safer default for a large public system until your evidence says otherwise.
33
+
34
+ ## The ten checkpoints
35
+
36
+ 1. [Foundations and database boundaries](01-foundations.md)
37
+ 2. [Local development](02-local-development.md)
38
+ 3. [RubyDB embedded mode](03-embedded-rubydb.md)
39
+ 4. [Rails and complex application code](04-rails-complex-apps.md)
40
+ 5. [RubyDB server production setup](05-rubydb-production-server.md)
41
+ 6. [PostgreSQL for large applications](06-postgresql-massive-apps.md)
42
+ 7. [A hybrid microservice architecture](07-hybrid-microservices.md)
43
+ 8. [Migrations, backups, and recovery](08-migrations-backups-recovery.md)
44
+ 9. [Observability, security, and scale](09-observability-security-scale.md)
45
+ 10. [Release readiness](10-release-readiness.md)
46
+
47
+ ## Prerequisites
48
+
49
+ Install a supported Ruby version, Git, and Bundler. From a clone of this
50
+ repository:
51
+
52
+ ```sh
53
+ git clone https://github.com/aldanedev-create/rubydb.git
54
+ cd rubydb
55
+ bundle install
56
+ bundle exec rspec
57
+ ```
58
+
59
+ The test suite is useful evidence about the repository, but it is not evidence
60
+ about your application. Later lessons add application queries, restore drills,
61
+ and deployment checks.
62
+
63
+ ## Checkpoint
64
+
65
+ Before continuing, write down these three answers in your project runbook:
66
+
67
+ * Which database owns business-critical data?
68
+ * How many processes and hosts will connect to it?
69
+ * What recovery point objective (RPO) and recovery time objective (RTO) must be
70
+ met?
71
+
72
+ If the answers are unknown, the application is not ready for a production
73
+ database choice. Continue to lesson 2 to build a reproducible local baseline.