rubydb 0.1.4 → 0.1.6

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 (469) 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 +16 -5
  14. data/.rubocop.yml +50 -44
  15. data/.standard.yml +9 -14
  16. data/ARCHITECTURE.md +21 -21
  17. data/CHANGELOG.md +57 -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 +168 -12
  24. data/ROADMAP.md +27 -27
  25. data/Rakefile +76 -71
  26. data/SECURITY.md +54 -54
  27. data/SUPPORT.md +14 -14
  28. data/accelerator/bin/SHA256SUMS +6 -0
  29. data/accelerator/bin/rubydb-accelerator-darwin-amd64 +0 -0
  30. data/accelerator/bin/rubydb-accelerator-darwin-arm64 +0 -0
  31. data/accelerator/bin/rubydb-accelerator-linux-amd64 +0 -0
  32. data/accelerator/bin/rubydb-accelerator-linux-arm64 +0 -0
  33. data/accelerator/bin/rubydb-accelerator-windows-amd64.exe +0 -0
  34. data/accelerator/bin/rubydb-accelerator-windows-arm64.exe +0 -0
  35. data/accelerator/cmd/rubydb-accelerator/main.go +11 -0
  36. data/accelerator/go.mod +3 -0
  37. data/accelerator/internal/execution/aggregate.go +94 -0
  38. data/accelerator/internal/execution/distinct.go +22 -0
  39. data/accelerator/internal/execution/filter.go +73 -0
  40. data/accelerator/internal/execution/join.go +79 -0
  41. data/accelerator/internal/execution/operators.go +167 -0
  42. data/accelerator/internal/execution/scan.go +20 -0
  43. data/accelerator/internal/execution/sort.go +62 -0
  44. data/accelerator/internal/execution/types.go +136 -0
  45. data/accelerator/internal/execution/value.go +67 -0
  46. data/accelerator/internal/memory/arena.go +47 -0
  47. data/accelerator/internal/memory/reuse.go +22 -0
  48. data/accelerator/internal/metrics/registry.go +67 -0
  49. data/accelerator/internal/parallel/bounded_queue.go +56 -0
  50. data/accelerator/internal/parallel/scheduler.go +47 -0
  51. data/accelerator/internal/parallel/worker_pool.go +53 -0
  52. data/accelerator/internal/protocol/cancellation.go +48 -0
  53. data/accelerator/internal/protocol/columnar.go +263 -0
  54. data/accelerator/internal/protocol/frame.go +187 -0
  55. data/accelerator/internal/runtime/worker.go +521 -0
  56. data/accelerator/internal/storage/page_reader.go +81 -0
  57. data/accelerator/internal/storage/snapshot_scan.go +539 -0
  58. data/accelerator/internal/wal/checksum.go +13 -0
  59. data/accelerator/internal/wal/compression.go +41 -0
  60. data/accelerator/internal/wal/group_commit.go +24 -0
  61. data/accelerator/internal/wal/record_encoder.go +40 -0
  62. data/adapters/activerecord/Gemfile +11 -11
  63. data/adapters/activerecord/README.md +8 -3
  64. data/adapters/activerecord/lib/active_record/connection_adapters/rubydb_adapter.rb +881 -879
  65. data/adapters/activerecord/rubydb-activerecord.gemspec +21 -21
  66. data/adapters/activerecord/spec/rubydb_adapter_integration_spec.rb +143 -143
  67. data/adapters/ruby/README.md +18 -18
  68. data/adapters/sequel/README.md +11 -11
  69. data/config/monitoring/prometheus-alerts.yml +39 -39
  70. data/config/production.yml +36 -36
  71. data/docs/README.md +77 -71
  72. data/docs/architecture/concurrency.md +14 -14
  73. data/docs/architecture/current-state.md +125 -125
  74. data/docs/architecture/execution-engine.md +25 -25
  75. data/docs/architecture/go-accelerator.md +179 -0
  76. data/docs/architecture/indexes.md +19 -19
  77. data/docs/architecture/mvcc.md +19 -19
  78. data/docs/architecture/overview.md +13 -13
  79. data/docs/architecture/pages.md +11 -11
  80. data/docs/architecture/production-roadmap.md +82 -82
  81. data/docs/architecture/query-planner.md +20 -20
  82. data/docs/architecture/recovery.md +18 -18
  83. data/docs/architecture/sql-engine.md +12 -12
  84. data/docs/architecture/storage-engine.md +14 -14
  85. data/docs/architecture/transactions.md +10 -10
  86. data/docs/architecture/wal.md +28 -28
  87. data/docs/cli-cheatsheet.md +98 -98
  88. data/docs/cli.md +299 -275
  89. data/docs/contributing/architecture.md +9 -9
  90. data/docs/contributing/benchmarking.md +30 -14
  91. data/docs/contributing/development.md +16 -16
  92. data/docs/contributing/release-process.md +49 -49
  93. data/docs/contributing/testing.md +16 -16
  94. data/docs/debugging.md +229 -229
  95. data/docs/developer/branching.md +10 -10
  96. data/docs/developer/database-diff.md +10 -10
  97. data/docs/developer/local-development.md +49 -17
  98. data/docs/developer/snapshots.md +9 -9
  99. data/docs/developer/temporal-data.md +10 -10
  100. data/docs/developer-guide.md +297 -297
  101. data/docs/getting-started/first-database.md +16 -16
  102. data/docs/getting-started/first-query.md +13 -13
  103. data/docs/getting-started/installation.md +19 -19
  104. data/docs/getting-started/local-to-production.md +300 -300
  105. data/docs/getting-started/quickstart.md +17 -17
  106. data/docs/getting-started/rails.md +16 -16
  107. data/docs/hardening_backlog.md +93 -93
  108. data/docs/lessons-learned.md +112 -112
  109. data/docs/operations/backups.md +33 -33
  110. data/docs/operations/disaster-recovery.md +31 -31
  111. data/docs/operations/failover.md +30 -30
  112. data/docs/operations/monitoring.md +25 -25
  113. data/docs/operations/production-guide.md +295 -295
  114. data/docs/operations/production-runbook.md +45 -45
  115. data/docs/operations/replication.md +33 -33
  116. data/docs/operations/restore.md +6 -6
  117. data/docs/operations/runbook.md +34 -34
  118. data/docs/operations/upgrades.md +14 -14
  119. data/docs/operations/workload-testing.md +17 -17
  120. data/docs/production-readiness.md +118 -118
  121. data/docs/production_validation.md +150 -150
  122. data/docs/rails/active-record.md +11 -11
  123. data/docs/rails/compatibility-guide.md +90 -90
  124. data/docs/rails/database-yml.md +92 -92
  125. data/docs/rails/installation.md +17 -17
  126. data/docs/rails/migrations.md +17 -17
  127. data/docs/rails/production.md +82 -82
  128. data/docs/rails/troubleshooting.md +18 -18
  129. data/docs/release.md +25 -25
  130. data/docs/server/architecture.md +10 -10
  131. data/docs/server/authentication.md +10 -10
  132. data/docs/server/configuration.md +16 -16
  133. data/docs/server/connection-pooling.md +10 -10
  134. data/docs/server/deployment.md +10 -10
  135. data/docs/server/protocol.md +12 -12
  136. data/docs/sql/compatibility-guide.md +82 -82
  137. data/docs/sql/compatibility.md +39 -39
  138. data/docs/sql/data-types.md +10 -10
  139. data/docs/sql/functions.md +9 -9
  140. data/docs/sql/joins.md +9 -9
  141. data/docs/sql/operators.md +9 -9
  142. data/docs/sql/sqlite-compatibility.md +21 -21
  143. data/docs/sql/syntax.md +10 -10
  144. data/docs/sql/transactions.md +10 -10
  145. data/docs/troubleshooting.md +244 -244
  146. data/lessons/01-foundations.md +73 -0
  147. data/lessons/02-local-development.md +121 -0
  148. data/lessons/03-embedded-rubydb.md +99 -0
  149. data/lessons/04-rails-complex-apps.md +138 -0
  150. data/lessons/05-rubydb-production-server.md +237 -0
  151. data/lessons/06-postgresql-massive-apps.md +96 -0
  152. data/lessons/07-hybrid-microservices.md +179 -0
  153. data/lessons/08-migrations-backups-recovery.md +86 -0
  154. data/lessons/09-observability-security-scale.md +87 -0
  155. data/lessons/10-release-readiness.md +192 -0
  156. data/lessons/11-community-adapter.md +323 -0
  157. data/lessons/12-rails-ecommerce-pressure.md +263 -0
  158. data/lib/rubydb/accelerator/client.rb +451 -0
  159. data/lib/rubydb/accelerator/error.rb +22 -0
  160. data/lib/rubydb/accelerator/manager.rb +606 -0
  161. data/lib/rubydb/accelerator.rb +13 -0
  162. data/lib/rubydb/backup/archive.rb +332 -334
  163. data/lib/rubydb/backup/backup.rb +400 -401
  164. data/lib/rubydb/backup/incremental.rb +349 -353
  165. data/lib/rubydb/backup/restore.rb +289 -290
  166. data/lib/rubydb/backup/snapshot.rb +265 -267
  167. data/lib/rubydb/backup/verification.rb +276 -279
  168. data/lib/rubydb/branching/branch.rb +181 -181
  169. data/lib/rubydb/branching/branch_manager.rb +307 -311
  170. data/lib/rubydb/branching/branch_metadata.rb +140 -140
  171. data/lib/rubydb/branching/checkout.rb +165 -166
  172. data/lib/rubydb/branching/copy_on_write.rb +272 -272
  173. data/lib/rubydb/branching/diff.rb +137 -138
  174. data/lib/rubydb/branching/merge.rb +282 -285
  175. data/lib/rubydb/build_info.rb +15 -15
  176. data/lib/rubydb/catalog/catalog.rb +391 -391
  177. data/lib/rubydb/catalog/column.rb +112 -112
  178. data/lib/rubydb/catalog/constraint.rb +180 -180
  179. data/lib/rubydb/catalog/database.rb +184 -184
  180. data/lib/rubydb/catalog/index.rb +97 -97
  181. data/lib/rubydb/catalog/schema.rb +103 -103
  182. data/lib/rubydb/catalog/sequence.rb +90 -90
  183. data/lib/rubydb/catalog/system_catalog.rb +698 -698
  184. data/lib/rubydb/catalog/table.rb +178 -178
  185. data/lib/rubydb/catalog/trigger.rb +102 -102
  186. data/lib/rubydb/catalog/view.rb +66 -66
  187. data/lib/rubydb/cli/application.rb +168 -163
  188. data/lib/rubydb/cli/commands/accelerator.rb +72 -0
  189. data/lib/rubydb/cli/commands/backup.rb +80 -81
  190. data/lib/rubydb/cli/commands/branch.rb +72 -72
  191. data/lib/rubydb/cli/commands/checkout.rb +54 -54
  192. data/lib/rubydb/cli/commands/create.rb +58 -58
  193. data/lib/rubydb/cli/commands/diff.rb +76 -77
  194. data/lib/rubydb/cli/commands/doctor.rb +77 -74
  195. data/lib/rubydb/cli/commands/drop.rb +57 -57
  196. data/lib/rubydb/cli/commands/init.rb +101 -102
  197. data/lib/rubydb/cli/commands/inspect.rb +95 -95
  198. data/lib/rubydb/cli/commands/merge.rb +63 -63
  199. data/lib/rubydb/cli/commands/migrate.rb +62 -62
  200. data/lib/rubydb/cli/commands/restart.rb +42 -39
  201. data/lib/rubydb/cli/commands/restore.rb +121 -121
  202. data/lib/rubydb/cli/commands/shell.rb +365 -365
  203. data/lib/rubydb/cli/commands/snapshot.rb +79 -79
  204. data/lib/rubydb/cli/commands/start.rb +88 -82
  205. data/lib/rubydb/cli/commands/status.rb +96 -92
  206. data/lib/rubydb/cli/commands/stop.rb +47 -47
  207. data/lib/rubydb/cli/commands/vacuum.rb +58 -58
  208. data/lib/rubydb/cli/formatter.rb +221 -221
  209. data/lib/rubydb/cli/output.rb +168 -168
  210. data/lib/rubydb/client/client.rb +309 -304
  211. data/lib/rubydb/client/connection.rb +429 -415
  212. data/lib/rubydb/client/connection_pool.rb +168 -168
  213. data/lib/rubydb/client/connection_url.rb +96 -96
  214. data/lib/rubydb/client/prepared_statement.rb +60 -60
  215. data/lib/rubydb/client/result.rb +127 -123
  216. data/lib/rubydb/client/statement.rb +52 -52
  217. data/lib/rubydb/client/transaction.rb +130 -130
  218. data/lib/rubydb/concurrency/concurrency.rb +19 -19
  219. data/lib/rubydb/concurrency/deadlock_detector.rb +148 -150
  220. data/lib/rubydb/concurrency/latch.rb +101 -101
  221. data/lib/rubydb/concurrency/lock_graph.rb +163 -165
  222. data/lib/rubydb/concurrency/mutex.rb +181 -183
  223. data/lib/rubydb/concurrency/rw_lock.rb +180 -180
  224. data/lib/rubydb/concurrency/scheduler.rb +248 -250
  225. data/lib/rubydb/concurrency/worker_pool.rb +145 -143
  226. data/lib/rubydb/configuration/config.rb +170 -170
  227. data/lib/rubydb/configuration/defaults.rb +191 -179
  228. data/lib/rubydb/configuration/environment.rb +152 -152
  229. data/lib/rubydb/configuration/parser.rb +185 -185
  230. data/lib/rubydb/configuration/validation.rb +228 -221
  231. data/lib/rubydb/constants.rb +74 -74
  232. data/lib/rubydb/constraints/check.rb +181 -181
  233. data/lib/rubydb/constraints/constraint.rb +101 -101
  234. data/lib/rubydb/constraints/foreign_key.rb +130 -130
  235. data/lib/rubydb/constraints/not_null.rb +64 -64
  236. data/lib/rubydb/constraints/primary_key.rb +99 -99
  237. data/lib/rubydb/constraints/unique.rb +106 -108
  238. data/lib/rubydb/constraints/validator.rb +349 -350
  239. data/lib/rubydb/errors/authentication_error.rb +10 -10
  240. data/lib/rubydb/errors/authorization_error.rb +23 -23
  241. data/lib/rubydb/errors/client_error.rb +10 -10
  242. data/lib/rubydb/errors/configuration_error.rb +10 -10
  243. data/lib/rubydb/errors/connection_error.rb +10 -10
  244. data/lib/rubydb/errors/constraint_error.rb +23 -23
  245. data/lib/rubydb/errors/corruption_error.rb +10 -10
  246. data/lib/rubydb/errors/database_error.rb +10 -10
  247. data/lib/rubydb/errors/error.rb +20 -20
  248. data/lib/rubydb/errors/execution_error.rb +10 -10
  249. data/lib/rubydb/errors/parser_error.rb +10 -10
  250. data/lib/rubydb/errors/recovery_error.rb +10 -10
  251. data/lib/rubydb/errors/replication_error.rb +10 -10
  252. data/lib/rubydb/errors/server_error.rb +6 -6
  253. data/lib/rubydb/errors/storage_error.rb +10 -10
  254. data/lib/rubydb/errors/transaction_error.rb +10 -10
  255. data/lib/rubydb/execution/accelerator_dispatch.rb +30 -0
  256. data/lib/rubydb/execution/aggregate_executor.rb +134 -138
  257. data/lib/rubydb/execution/cost_model.rb +72 -0
  258. data/lib/rubydb/execution/delete_executor.rb +110 -112
  259. data/lib/rubydb/execution/distinct_executor.rb +131 -135
  260. data/lib/rubydb/execution/executor.rb +1544 -1188
  261. data/lib/rubydb/execution/expression.rb +191 -193
  262. data/lib/rubydb/execution/index_scan.rb +142 -142
  263. data/lib/rubydb/execution/insert_executor.rb +215 -217
  264. data/lib/rubydb/execution/join_executor.rb +243 -249
  265. data/lib/rubydb/execution/limit_executor.rb +83 -85
  266. data/lib/rubydb/execution/operator_selection.rb +57 -0
  267. data/lib/rubydb/execution/optimizer.rb +227 -215
  268. data/lib/rubydb/execution/physical_plan.rb +47 -0
  269. data/lib/rubydb/execution/plan.rb +355 -353
  270. data/lib/rubydb/execution/planner.rb +508 -536
  271. data/lib/rubydb/execution/predicate.rb +235 -235
  272. data/lib/rubydb/execution/scan.rb +49 -49
  273. data/lib/rubydb/execution/sequential_scan.rb +63 -63
  274. data/lib/rubydb/execution/sort_executor.rb +194 -185
  275. data/lib/rubydb/execution/update_executor.rb +160 -162
  276. data/lib/rubydb/functions/aggregate.rb +70 -70
  277. data/lib/rubydb/functions/date_functions.rb +274 -278
  278. data/lib/rubydb/functions/function.rb +85 -85
  279. data/lib/rubydb/functions/json_functions.rb +231 -215
  280. data/lib/rubydb/functions/numeric_functions.rb +346 -346
  281. data/lib/rubydb/functions/scalar.rb +52 -52
  282. data/lib/rubydb/functions/string_functions.rb +383 -383
  283. data/lib/rubydb/functions/system_functions.rb +258 -246
  284. data/lib/rubydb/history/as_of.rb +238 -238
  285. data/lib/rubydb/history/change.rb +105 -105
  286. data/lib/rubydb/history/history.rb +131 -131
  287. data/lib/rubydb/history/history_manager.rb +228 -229
  288. data/lib/rubydb/history/temporal_query.rb +202 -202
  289. data/lib/rubydb/history/timeline.rb +144 -144
  290. data/lib/rubydb/indexes/btree.rb +215 -186
  291. data/lib/rubydb/indexes/btree_cursor.rb +258 -258
  292. data/lib/rubydb/indexes/btree_node.rb +384 -385
  293. data/lib/rubydb/indexes/hash_index.rb +150 -150
  294. data/lib/rubydb/indexes/index.rb +71 -71
  295. data/lib/rubydb/indexes/index_manager.rb +408 -406
  296. data/lib/rubydb/indexes/index_scan.rb +466 -470
  297. data/lib/rubydb/migrations/migration.rb +253 -254
  298. data/lib/rubydb/migrations/migration_lock.rb +146 -146
  299. data/lib/rubydb/migrations/migration_manager.rb +187 -176
  300. data/lib/rubydb/migrations/migration_version.rb +71 -71
  301. data/lib/rubydb/migrations/schema_diff.rb +211 -211
  302. data/lib/rubydb/migrations/schema_version.rb +64 -64
  303. data/lib/rubydb/monitoring/events.rb +155 -160
  304. data/lib/rubydb/monitoring/health.rb +216 -222
  305. data/lib/rubydb/monitoring/logger.rb +188 -193
  306. data/lib/rubydb/monitoring/metrics.rb +363 -359
  307. data/lib/rubydb/monitoring/performance.rb +176 -176
  308. data/lib/rubydb/monitoring/statistics.rb +168 -170
  309. data/lib/rubydb/mvcc/garbage_collector.rb +199 -199
  310. data/lib/rubydb/mvcc/mvcc.rb +16 -16
  311. data/lib/rubydb/mvcc/snapshot.rb +146 -147
  312. data/lib/rubydb/mvcc/vacuum.rb +180 -180
  313. data/lib/rubydb/mvcc/version.rb +106 -106
  314. data/lib/rubydb/mvcc/version_store.rb +396 -398
  315. data/lib/rubydb/mvcc/visibility.rb +107 -109
  316. data/lib/rubydb/protocol/capabilities.rb +125 -125
  317. data/lib/rubydb/protocol/decoder.rb +142 -145
  318. data/lib/rubydb/protocol/encoder.rb +131 -136
  319. data/lib/rubydb/protocol/handshake.rb +306 -305
  320. data/lib/rubydb/protocol/message.rb +121 -121
  321. data/lib/rubydb/protocol/parameter_binder.rb +101 -0
  322. data/lib/rubydb/protocol/protocol.rb +276 -277
  323. data/lib/rubydb/protocol/version.rb +54 -54
  324. data/lib/rubydb/rails/adapter.rb +245 -239
  325. data/lib/rubydb/rails/connection.rb +312 -314
  326. data/lib/rubydb/rails/database_statements.rb +122 -122
  327. data/lib/rubydb/rails/migration.rb +131 -131
  328. data/lib/rubydb/rails/quoting.rb +109 -109
  329. data/lib/rubydb/rails/result.rb +117 -117
  330. data/lib/rubydb/rails/schema_statements.rb +339 -339
  331. data/lib/rubydb/rails/transaction.rb +105 -105
  332. data/lib/rubydb/rails/type.rb +126 -126
  333. data/lib/rubydb/recovery/checkpoint.rb +261 -257
  334. data/lib/rubydb/recovery/consistency.rb +457 -467
  335. data/lib/rubydb/recovery/corruption_detector.rb +5 -5
  336. data/lib/rubydb/recovery/crash_recovery.rb +381 -387
  337. data/lib/rubydb/recovery/recovery_manager.rb +204 -206
  338. data/lib/rubydb/recovery/redo.rb +235 -237
  339. data/lib/rubydb/recovery/undo.rb +204 -206
  340. data/lib/rubydb/replication/failover.rb +5 -5
  341. data/lib/rubydb/replication/fencing.rb +63 -63
  342. data/lib/rubydb/replication/primary.rb +461 -450
  343. data/lib/rubydb/replication/replica.rb +382 -384
  344. data/lib/rubydb/replication/replication_log.rb +194 -200
  345. data/lib/rubydb/replication/replication_manager.rb +307 -308
  346. data/lib/rubydb/replication/replication_slot.rb +293 -295
  347. data/lib/rubydb/replication/replication_stream.rb +198 -201
  348. data/lib/rubydb/rubydb.rb +570 -560
  349. data/lib/rubydb/security/access_control.rb +252 -254
  350. data/lib/rubydb/security/audit_log.rb +209 -213
  351. data/lib/rubydb/security/authentication.rb +302 -302
  352. data/lib/rubydb/security/authorization.rb +282 -282
  353. data/lib/rubydb/security/credentials.rb +192 -196
  354. data/lib/rubydb/security/password.rb +205 -215
  355. data/lib/rubydb/security/permissions.rb +74 -74
  356. data/lib/rubydb/security/role.rb +99 -101
  357. data/lib/rubydb/security/user.rb +86 -86
  358. data/lib/rubydb/server/connection.rb +383 -366
  359. data/lib/rubydb/server/connection_pool.rb +193 -193
  360. data/lib/rubydb/server/lifecycle.rb +227 -228
  361. data/lib/rubydb/server/listener.rb +139 -136
  362. data/lib/rubydb/server/request_handler.rb +277 -276
  363. data/lib/rubydb/server/server.rb +363 -364
  364. data/lib/rubydb/server/session.rb +416 -369
  365. data/lib/rubydb/server/worker.rb +206 -210
  366. data/lib/rubydb/server/worker_pool.rb +168 -168
  367. data/lib/rubydb/sql/ast/alter_table.rb +169 -169
  368. data/lib/rubydb/sql/ast/begin_transaction.rb +47 -47
  369. data/lib/rubydb/sql/ast/commit.rb +37 -37
  370. data/lib/rubydb/sql/ast/constraint.rb +92 -83
  371. data/lib/rubydb/sql/ast/create_database.rb +41 -41
  372. data/lib/rubydb/sql/ast/create_index.rb +61 -61
  373. data/lib/rubydb/sql/ast/create_schema.rb +52 -52
  374. data/lib/rubydb/sql/ast/create_table.rb +187 -187
  375. data/lib/rubydb/sql/ast/delete.rb +54 -54
  376. data/lib/rubydb/sql/ast/drop_database.rb +41 -41
  377. data/lib/rubydb/sql/ast/drop_index.rb +41 -41
  378. data/lib/rubydb/sql/ast/drop_schema.rb +49 -49
  379. data/lib/rubydb/sql/ast/drop_table.rb +49 -49
  380. data/lib/rubydb/sql/ast/explain.rb +64 -64
  381. data/lib/rubydb/sql/ast/expression.rb +617 -604
  382. data/lib/rubydb/sql/ast/insert.rb +66 -66
  383. data/lib/rubydb/sql/ast/node.rb +42 -42
  384. data/lib/rubydb/sql/ast/rollback.rb +63 -63
  385. data/lib/rubydb/sql/ast/savepoint.rb +59 -59
  386. data/lib/rubydb/sql/ast/select.rb +88 -88
  387. data/lib/rubydb/sql/ast/set_operation.rb +22 -20
  388. data/lib/rubydb/sql/ast/trigger.rb +35 -29
  389. data/lib/rubydb/sql/ast/update.rb +88 -88
  390. data/lib/rubydb/sql/ast/vacuum.rb +19 -19
  391. data/lib/rubydb/sql/ast/view.rb +38 -32
  392. data/lib/rubydb/sql/ast/with.rb +32 -32
  393. data/lib/rubydb/sql/grammar.rb +86 -86
  394. data/lib/rubydb/sql/keywords.rb +156 -156
  395. data/lib/rubydb/sql/lexer.rb +209 -214
  396. data/lib/rubydb/sql/operators.rb +100 -100
  397. data/lib/rubydb/sql/parser.rb +1167 -1170
  398. data/lib/rubydb/sql/planner/analyzer.rb +283 -302
  399. data/lib/rubydb/sql/planner/binder.rb +537 -550
  400. data/lib/rubydb/sql/planner/type_checker.rb +427 -431
  401. data/lib/rubydb/sql/token.rb +210 -210
  402. data/lib/rubydb/storage/buffer_frame.rb +44 -44
  403. data/lib/rubydb/storage/buffer_pool.rb +155 -155
  404. data/lib/rubydb/storage/database_lock.rb +74 -74
  405. data/lib/rubydb/storage/deserializer.rb +332 -342
  406. data/lib/rubydb/storage/engine.rb +2409 -2330
  407. data/lib/rubydb/storage/file_manager.rb +191 -187
  408. data/lib/rubydb/storage/free_space_map.rb +79 -81
  409. data/lib/rubydb/storage/page.rb +92 -94
  410. data/lib/rubydb/storage/page_allocator.rb +852 -855
  411. data/lib/rubydb/storage/page_header.rb +63 -67
  412. data/lib/rubydb/storage/page_manager.rb +127 -131
  413. data/lib/rubydb/storage/record.rb +58 -58
  414. data/lib/rubydb/storage/row.rb +78 -78
  415. data/lib/rubydb/storage/serializer.rb +51 -51
  416. data/lib/rubydb/storage/snapshot_reader.rb +167 -0
  417. data/lib/rubydb/storage/storage_layout.rb +151 -151
  418. data/lib/rubydb/storage/storage_manager.rb +114 -114
  419. data/lib/rubydb/storage/tuple.rb +458 -461
  420. data/lib/rubydb/storage/visibility_map.rb +964 -973
  421. data/lib/rubydb/transactions/commit_manager.rb +219 -220
  422. data/lib/rubydb/transactions/isolation.rb +98 -98
  423. data/lib/rubydb/transactions/lock.rb +76 -76
  424. data/lib/rubydb/transactions/lock_manager.rb +359 -362
  425. data/lib/rubydb/transactions/savepoint.rb +142 -143
  426. data/lib/rubydb/transactions/transaction.rb +214 -215
  427. data/lib/rubydb/transactions/transaction_id.rb +84 -84
  428. data/lib/rubydb/transactions/transaction_log.rb +256 -257
  429. data/lib/rubydb/transactions/transaction_manager.rb +434 -435
  430. data/lib/rubydb/types/bigint.rb +36 -36
  431. data/lib/rubydb/types/blob.rb +37 -37
  432. data/lib/rubydb/types/boolean.rb +34 -34
  433. data/lib/rubydb/types/date.rb +39 -39
  434. data/lib/rubydb/types/decimal.rb +48 -48
  435. data/lib/rubydb/types/float.rb +34 -34
  436. data/lib/rubydb/types/integer.rb +36 -36
  437. data/lib/rubydb/types/json.rb +41 -41
  438. data/lib/rubydb/types/null.rb +34 -34
  439. data/lib/rubydb/types/smallint.rb +36 -36
  440. data/lib/rubydb/types/text.rb +37 -37
  441. data/lib/rubydb/types/time.rb +46 -46
  442. data/lib/rubydb/types/timestamp.rb +39 -39
  443. data/lib/rubydb/types/type.rb +119 -119
  444. data/lib/rubydb/types/uuid.rb +47 -47
  445. data/lib/rubydb/types/varchar.rb +37 -37
  446. data/lib/rubydb/version.rb +32 -32
  447. data/lib/rubydb/wal/archive.rb +207 -193
  448. data/lib/rubydb/wal/checkpoint.rb +181 -183
  449. data/lib/rubydb/wal/lsn.rb +94 -94
  450. data/lib/rubydb/wal/reader.rb +259 -260
  451. data/lib/rubydb/wal/record.rb +105 -105
  452. data/lib/rubydb/wal/segment.rb +193 -193
  453. data/lib/rubydb/wal/wal.rb +481 -452
  454. data/lib/rubydb/wal/writer.rb +236 -236
  455. data/lib/rubydb.rb +7 -7
  456. data/packaging/docker/docker-compose.failover.yml +43 -43
  457. data/packaging/homebrew/rubydb.rb +19 -19
  458. data/rubydb.gemspec +70 -57
  459. data/scripts/benchmark +7 -7
  460. data/scripts/build_accelerator +49 -0
  461. data/scripts/durability_drill +37 -37
  462. data/scripts/fuzz +63 -63
  463. data/scripts/release +77 -42
  464. data/scripts/release_check +43 -43
  465. data/scripts/replication_failover_drill +268 -250
  466. data/scripts/replication_network_failover_drill +287 -255
  467. data/scripts/restore_drill +45 -45
  468. data/scripts/security +45 -0
  469. metadata +102 -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.