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,295 +1,295 @@
1
- # RubyDB production operations guide
2
-
3
- This guide describes a controlled production deployment for applications that
4
- fit RubyDB’s documented feature surface. It is an operational companion to
5
- the [production runbook](production-runbook.md), [disaster recovery guide](disaster-recovery.md),
6
- and [monitoring guide](monitoring.md). It does not turn the current project
7
- into a universal PostgreSQL, MySQL, or SQLite replacement.
8
-
9
- ## Deployment decision
10
-
11
- Choose embedded mode only when one process owns the database directory and the
12
- application accepts process-local availability. Use server mode when web,
13
- worker, migration, or administrative processes need concurrent access. Put
14
- the database directory on storage with documented durability and rename/
15
- flush semantics. Do not place it on an untested shared filesystem.
16
-
17
- Before launch, validate the application’s schema, generated SQL, migrations,
18
- backup/restore path, concurrency profile, and failure behavior against the
19
- exact RubyDB version and configuration that will be deployed.
20
-
21
- ## Reference topology
22
-
23
- ```text
24
- clients/web/workers -> TLS -> RubyDB server -> private database volume
25
- |-> WAL/checkpoints
26
- |-> verified backup destination
27
- |-> metrics/log sink
28
- optional replica --------------------^
29
- ```
30
-
31
- A replica is not a backup. A backup is not a fencing system. An application
32
- load balancer health check is not proof that a primary is safe to write. Keep
33
- these responsibilities separate.
34
-
35
- ## Complete first deployment
36
-
37
- The following is a reference deployment for a Rails or regular Ruby
38
- application. Replace paths, hostnames, users, and limits with values approved
39
- by your infrastructure team.
40
-
41
- ### 1. Install and provision the server
42
-
43
- Pin the RubyDB gem version on the database host. Do not use an unpinned
44
- prerelease in a production deployment:
45
-
46
- ```sh
47
- gem install rubydb -v 0.1.0
48
- useradd --system --home-dir /var/lib/rubydb --shell /usr/sbin/nologin rubydb
49
- install -d -o rubydb -g rubydb -m 0700 /var/lib/rubydb/data
50
- install -d -o rubydb -g rubydb -m 0750 /var/log/rubydb
51
- install -d -o root -g rubydb -m 0750 /etc/rubydb
52
- ```
53
-
54
- Use a persistent local volume for `/var/lib/rubydb/data`. Keep backups on a
55
- separate failure domain. The server account should not own application source,
56
- certificate private keys, or unrelated host data.
57
-
58
- ### 2. Configure the server
59
-
60
- Start from the repository’s `config/production.yml` and place a reviewed copy
61
- at `/etc/rubydb/production.yml`. Supply required secrets through the service
62
- manager or secret store. At minimum, configure:
63
-
64
- ```text
65
- RUBYDB_HOST=0.0.0.0
66
- RUBYDB_PORT=7432
67
- RUBYDB_DATA_DIR=/var/lib/rubydb/data
68
- RUBYDB_LOG_DIR=/var/log/rubydb
69
- RUBYDB_USERNAME=app_rw
70
- RUBYDB_PASSWORD=<secret-manager-value>
71
- RUBYDB_SSL_ENABLED=true
72
- RUBYDB_SSL_CERT_FILE=/etc/rubydb/tls/server.crt
73
- RUBYDB_SSL_KEY_FILE=/etc/rubydb/tls/server.key
74
- RUBYDB_SSL_CA_FILE=/etc/rubydb/tls/ca.crt
75
- RUBYDB_SSL_VERIFY_PEER=true
76
- ```
77
-
78
- The server’s TLS private key and application password must be readable only by
79
- the service or secret-management mechanism. Restrict port `7432` to the Rails
80
- and worker network; do not expose it to the public internet.
81
-
82
- ### 3. Start and verify the server
83
-
84
- Run it under systemd, a supervised container, or an equivalent process
85
- manager. The CLI configuration options must appear before the command:
86
-
87
- ```sh
88
- sudo -u rubydb env RUBYDB_USERNAME=app_rw RUBYDB_PASSWORD='from-secret-store' \
89
- rubydb --config /etc/rubydb/production.yml --env production start
90
- ```
91
-
92
- In a systemd unit, use an `EnvironmentFile` protected with mode `0600` or a
93
- native secret integration, then use:
94
-
95
- ```ini
96
- ExecStart=/usr/local/bin/rubydb --config /etc/rubydb/production.yml --env production start
97
- Restart=on-failure
98
- ```
99
-
100
- Verify from the application network, not only from the database host:
101
-
102
- ```sh
103
- rubydb --config /etc/rubydb/production.yml --env production status --json
104
- rubydb --config /etc/rubydb/production.yml --env production doctor --json
105
- ```
106
-
107
- Then run an authenticated TLS smoke query using the Ruby client and the same
108
- URL the application will use:
109
-
110
- ```sh
111
- RUBYDB_URL='rubydbs://app_rw:URL_ENCODED_PASSWORD@db.example.com:7432/app?verify_peer=true&ca_file=%2Fetc%2Frubydb%2Ftls%2Fca.crt' \
112
- ruby -rrubydb -e 'c=RubyDB::Client::Client.new(url: ENV.fetch("RUBYDB_URL")); p c.query("SELECT 1").to_hash; c.disconnect'
113
- ```
114
-
115
- ### 4. Configure a Rails application
116
-
117
- In the Rails application’s `config/database.yml`, select server mode and read
118
- the connection string from the deployment environment:
119
-
120
- ```yaml
121
- production:
122
- adapter: rubydb
123
- embedded: false
124
- url: <%= ENV.fetch("RUBYDB_URL") %>
125
- pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
126
- ```
127
-
128
- Set `RUBYDB_URL` through the platform secret store:
129
-
130
- ```text
131
- RUBYDB_URL=rubydbs://app_rw:URL_ENCODED_PASSWORD@db.example.com:7432/app?verify_peer=true&ca_file=%2Fetc%2Frubydb%2Ftls%2Fca.crt
132
- ```
133
-
134
- Deploy the Rails application, then run the migration once using a controlled
135
- release job, not concurrently from every web process:
136
-
137
- ```sh
138
- RAILS_ENV=production bundle exec rails db:migrate
139
- RAILS_ENV=production bundle exec rails runner 'puts User.count'
140
- ```
141
-
142
- The web and job processes connect to the server endpoint. They never mount or
143
- open `/var/lib/rubydb/data`.
144
-
145
- ### 5. Configure a regular Ruby application
146
-
147
- The regular client uses the same environment value:
148
-
149
- ```ruby
150
- require "rubydb"
151
-
152
- client = RubyDB::Client::Client.new(url: ENV.fetch("RUBYDB_URL"))
153
- begin
154
- client.query("SELECT 1")
155
- client.query("INSERT INTO audit_events (event_name) VALUES (?)", ["boot"])
156
- ensure
157
- client.disconnect
158
- end
159
- ```
160
-
161
- Use application-level idempotency for retried writes. A network timeout does
162
- not by itself prove that a commit was rolled back.
163
-
164
- ### 6. Accept traffic gradually
165
-
166
- Run a read/write smoke test, migration status check, backup, and representative
167
- workload before routing all traffic. Watch p95/p99 latency, errors, lock waits,
168
- active connections, WAL growth, checkpoint age, disk space, and memory during a
169
- canary period. Keep the previous application version and verified database
170
- backup available until the rollback window closes.
171
-
172
- The Rails URL example and URL option reference are also maintained in [Rails
173
- database configuration](../rails/database-yml.md).
174
-
175
- ## Configuration and service identity
176
-
177
- Run the server as a dedicated least-privilege account. Give it access only to
178
- the database, WAL, temporary, certificate, and backup paths it needs. Store
179
- passwords, peer tokens, private keys, and API credentials in a secret manager.
180
- Do not put secrets in YAML committed to the repository, process arguments, or
181
- logs.
182
-
183
- Pin the RubyDB version and configuration for each deployment. Review changes to
184
- durability mode, WAL retention, checkpoint thresholds, memory, connection
185
- limits, request deadlines, lock timeouts, and TLS/authentication as production
186
- changes. Keep a configuration checksum in the deployment record.
187
-
188
- ## Readiness checklist
189
-
190
- Before accepting traffic:
191
-
192
- * database directory is on approved storage with sufficient space and inodes;
193
- * service account and file permissions are verified;
194
- * TLS certificate, key, CA, hostname, and expiration are checked;
195
- * authentication and authorization deny an unauthenticated test client;
196
- * health and readiness checks exercise a real request path;
197
- * connection, request, lock, and shutdown timeouts are bounded;
198
- * schema/migrations have completed and version/checksum is recorded;
199
- * full backup has been created and restored into a fresh directory;
200
- * monitoring, alert routing, and log retention are active;
201
- * rollback and restore owners are named; and
202
- * a representative smoke query and write have passed.
203
-
204
- ## Capacity and resource limits
205
-
206
- Set explicit limits for connections, request duration, lock waits, result size,
207
- memory, worker count, WAL size, backup space, and file descriptors. Size the
208
- application pool below the server limit, leaving room for migrations,
209
- replication, health checks, and administration. A pool that equals the server
210
- limit can starve the control plane.
211
-
212
- Alert before exhaustion, not after it. Watch CPU, RSS, open files, disk bytes,
213
- free inodes, WAL bytes, checkpoint age/duration, active transactions, lock
214
- waits, pool utilization, errors, cancellations, and p95/p99 latency.
215
-
216
- ## Backup policy
217
-
218
- Define RPO and RTO with the application owner. At minimum, maintain verified
219
- full backups, protect them from the database host, encrypt them at rest and in
220
- transit, retain multiple generations, and record manifests/checksums. If using
221
- incremental or differential backups, retain their verified base and ordered
222
- chain.
223
-
224
- A successful backup command is not proof of recoverability. Regularly restore
225
- to an isolated directory, validate checksums and schema, run representative
226
- queries, compare critical row counts, and record elapsed restore time. Run a
227
- restore drill after format, backup, storage, or release changes.
228
-
229
- ## Upgrade procedure
230
-
231
- 1. Read the release notes, format compatibility, and migration notes.
232
- 2. Create and verify a new full backup.
233
- 3. Test the new version against a restored production-like copy.
234
- 4. Run schema and application smoke tests, including populated-table writes.
235
- 5. Drain or fence writes according to the deployment topology.
236
- 6. Upgrade one controlled instance and verify health, WAL, and metrics.
237
- 7. Re-enable traffic gradually and watch errors and latency.
238
- 8. Keep the rollback binary and backup available until the validation window
239
- closes.
240
-
241
- Never roll back by pointing an older binary at a directory whose format or
242
- metadata it cannot read. Use the documented restore/rollback path.
243
-
244
- ## Failover procedure
245
-
246
- RubyDB’s safe failover model requires a synchronized candidate and a durable
247
- fencing decision. A manual operator sequence is:
248
-
249
- 1. declare the incident and stop or isolate application writes;
250
- 2. verify the primary’s last acknowledged LSN and fence epoch;
251
- 3. confirm the candidate’s applied LSN and integrity;
252
- 4. fence the old primary at the process, host, storage, or network layer;
253
- 5. promote only after fencing is observable and durable;
254
- 6. point clients at the new primary and run smoke writes/reads;
255
- 7. monitor replication and stale-writer rejection; and
256
- 8. recover the old primary as a replica only after its state is understood.
257
-
258
- Automatic election requires an independently validated quorum, fencing,
259
- partition behavior, stale-primary rejection, and recovery procedure. Do not
260
- enable election based solely on a successful same-host test.
261
-
262
- ## Incident response
263
-
264
- Contain first: stop unsafe writes, protect the database directory, and record
265
- the timeline. Preserve logs, metrics, WAL, metadata, configuration, process
266
- state, and backup manifests. Use [troubleshooting](../troubleshooting.md) and
267
- [debugging](../debugging.md) for evidence collection.
268
-
269
- Classify the event as availability, durability, correctness, security, or
270
- capacity. Assign an incident owner and a recovery owner. Communicate whether
271
- commit outcomes are known, unknown, or confirmed rolled back. After recovery,
272
- verify application invariants rather than relying only on process health.
273
-
274
- ## TLS and secret rotation
275
-
276
- Stage new certificates and CA material, validate the chain and hostname with a
277
- test client, then switch through an atomic deployment/configuration change.
278
- Maintain an overlap window only if clients support it. Confirm old material is
279
- no longer accepted before revoking it. Rotate database passwords and peer
280
- tokens through the secret manager; audit access and avoid printing values.
281
-
282
- ## Maintenance
283
-
284
- Schedule vacuum, compaction, checkpoint, index maintenance, and backups with
285
- awareness of active readers and write load. Measure before and after. Use a
286
- copy for repair or compaction experiments. Verify reopen, checksums, row counts,
287
- indexes, and application smoke queries after maintenance.
288
-
289
- ## Production evidence
290
-
291
- The release record should contain the RubyDB commit, Ruby/Rails versions,
292
- configuration checksum, schema/migration version, backup manifest, restore
293
- drill result, benchmark/soak result, monitoring link, security review status,
294
- and known limitations. See [production readiness](../production-readiness.md)
295
- for the project-level boundaries.
1
+ # RubyDB production operations guide
2
+
3
+ This guide describes a controlled production deployment for applications that
4
+ fit RubyDB’s documented feature surface. It is an operational companion to
5
+ the [production runbook](production-runbook.md), [disaster recovery guide](disaster-recovery.md),
6
+ and [monitoring guide](monitoring.md). It does not turn the current project
7
+ into a universal PostgreSQL, MySQL, or SQLite replacement.
8
+
9
+ ## Deployment decision
10
+
11
+ Choose embedded mode only when one process owns the database directory and the
12
+ application accepts process-local availability. Use server mode when web,
13
+ worker, migration, or administrative processes need concurrent access. Put
14
+ the database directory on storage with documented durability and rename/
15
+ flush semantics. Do not place it on an untested shared filesystem.
16
+
17
+ Before launch, validate the application’s schema, generated SQL, migrations,
18
+ backup/restore path, concurrency profile, and failure behavior against the
19
+ exact RubyDB version and configuration that will be deployed.
20
+
21
+ ## Reference topology
22
+
23
+ ```text
24
+ clients/web/workers -> TLS -> RubyDB server -> private database volume
25
+ |-> WAL/checkpoints
26
+ |-> verified backup destination
27
+ |-> metrics/log sink
28
+ optional replica --------------------^
29
+ ```
30
+
31
+ A replica is not a backup. A backup is not a fencing system. An application
32
+ load balancer health check is not proof that a primary is safe to write. Keep
33
+ these responsibilities separate.
34
+
35
+ ## Complete first deployment
36
+
37
+ The following is a reference deployment for a Rails or regular Ruby
38
+ application. Replace paths, hostnames, users, and limits with values approved
39
+ by your infrastructure team.
40
+
41
+ ### 1. Install and provision the server
42
+
43
+ Pin the RubyDB gem version on the database host. Do not use an unpinned
44
+ prerelease in a production deployment:
45
+
46
+ ```sh
47
+ gem install rubydb -v 0.1.0
48
+ useradd --system --home-dir /var/lib/rubydb --shell /usr/sbin/nologin rubydb
49
+ install -d -o rubydb -g rubydb -m 0700 /var/lib/rubydb/data
50
+ install -d -o rubydb -g rubydb -m 0750 /var/log/rubydb
51
+ install -d -o root -g rubydb -m 0750 /etc/rubydb
52
+ ```
53
+
54
+ Use a persistent local volume for `/var/lib/rubydb/data`. Keep backups on a
55
+ separate failure domain. The server account should not own application source,
56
+ certificate private keys, or unrelated host data.
57
+
58
+ ### 2. Configure the server
59
+
60
+ Start from the repository’s `config/production.yml` and place a reviewed copy
61
+ at `/etc/rubydb/production.yml`. Supply required secrets through the service
62
+ manager or secret store. At minimum, configure:
63
+
64
+ ```text
65
+ RUBYDB_HOST=0.0.0.0
66
+ RUBYDB_PORT=7432
67
+ RUBYDB_DATA_DIR=/var/lib/rubydb/data
68
+ RUBYDB_LOG_DIR=/var/log/rubydb
69
+ RUBYDB_USERNAME=app_rw
70
+ RUBYDB_PASSWORD=<secret-manager-value>
71
+ RUBYDB_SSL_ENABLED=true
72
+ RUBYDB_SSL_CERT_FILE=/etc/rubydb/tls/server.crt
73
+ RUBYDB_SSL_KEY_FILE=/etc/rubydb/tls/server.key
74
+ RUBYDB_SSL_CA_FILE=/etc/rubydb/tls/ca.crt
75
+ RUBYDB_SSL_VERIFY_PEER=true
76
+ ```
77
+
78
+ The server’s TLS private key and application password must be readable only by
79
+ the service or secret-management mechanism. Restrict port `7432` to the Rails
80
+ and worker network; do not expose it to the public internet.
81
+
82
+ ### 3. Start and verify the server
83
+
84
+ Run it under systemd, a supervised container, or an equivalent process
85
+ manager. The CLI configuration options must appear before the command:
86
+
87
+ ```sh
88
+ sudo -u rubydb env RUBYDB_USERNAME=app_rw RUBYDB_PASSWORD='from-secret-store' \
89
+ rubydb --config /etc/rubydb/production.yml --env production start
90
+ ```
91
+
92
+ In a systemd unit, use an `EnvironmentFile` protected with mode `0600` or a
93
+ native secret integration, then use:
94
+
95
+ ```ini
96
+ ExecStart=/usr/local/bin/rubydb --config /etc/rubydb/production.yml --env production start
97
+ Restart=on-failure
98
+ ```
99
+
100
+ Verify from the application network, not only from the database host:
101
+
102
+ ```sh
103
+ rubydb --config /etc/rubydb/production.yml --env production status --json
104
+ rubydb --config /etc/rubydb/production.yml --env production doctor --json
105
+ ```
106
+
107
+ Then run an authenticated TLS smoke query using the Ruby client and the same
108
+ URL the application will use:
109
+
110
+ ```sh
111
+ RUBYDB_URL='rubydbs://app_rw:URL_ENCODED_PASSWORD@db.example.com:7432/app?verify_peer=true&ca_file=%2Fetc%2Frubydb%2Ftls%2Fca.crt' \
112
+ ruby -rrubydb -e 'c=RubyDB::Client::Client.new(url: ENV.fetch("RUBYDB_URL")); p c.query("SELECT 1").to_hash; c.disconnect'
113
+ ```
114
+
115
+ ### 4. Configure a Rails application
116
+
117
+ In the Rails application’s `config/database.yml`, select server mode and read
118
+ the connection string from the deployment environment:
119
+
120
+ ```yaml
121
+ production:
122
+ adapter: rubydb
123
+ embedded: false
124
+ url: <%= ENV.fetch("RUBYDB_URL") %>
125
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
126
+ ```
127
+
128
+ Set `RUBYDB_URL` through the platform secret store:
129
+
130
+ ```text
131
+ RUBYDB_URL=rubydbs://app_rw:URL_ENCODED_PASSWORD@db.example.com:7432/app?verify_peer=true&ca_file=%2Fetc%2Frubydb%2Ftls%2Fca.crt
132
+ ```
133
+
134
+ Deploy the Rails application, then run the migration once using a controlled
135
+ release job, not concurrently from every web process:
136
+
137
+ ```sh
138
+ RAILS_ENV=production bundle exec rails db:migrate
139
+ RAILS_ENV=production bundle exec rails runner 'puts User.count'
140
+ ```
141
+
142
+ The web and job processes connect to the server endpoint. They never mount or
143
+ open `/var/lib/rubydb/data`.
144
+
145
+ ### 5. Configure a regular Ruby application
146
+
147
+ The regular client uses the same environment value:
148
+
149
+ ```ruby
150
+ require "rubydb"
151
+
152
+ client = RubyDB::Client::Client.new(url: ENV.fetch("RUBYDB_URL"))
153
+ begin
154
+ client.query("SELECT 1")
155
+ client.query("INSERT INTO audit_events (event_name) VALUES (?)", ["boot"])
156
+ ensure
157
+ client.disconnect
158
+ end
159
+ ```
160
+
161
+ Use application-level idempotency for retried writes. A network timeout does
162
+ not by itself prove that a commit was rolled back.
163
+
164
+ ### 6. Accept traffic gradually
165
+
166
+ Run a read/write smoke test, migration status check, backup, and representative
167
+ workload before routing all traffic. Watch p95/p99 latency, errors, lock waits,
168
+ active connections, WAL growth, checkpoint age, disk space, and memory during a
169
+ canary period. Keep the previous application version and verified database
170
+ backup available until the rollback window closes.
171
+
172
+ The Rails URL example and URL option reference are also maintained in [Rails
173
+ database configuration](../rails/database-yml.md).
174
+
175
+ ## Configuration and service identity
176
+
177
+ Run the server as a dedicated least-privilege account. Give it access only to
178
+ the database, WAL, temporary, certificate, and backup paths it needs. Store
179
+ passwords, peer tokens, private keys, and API credentials in a secret manager.
180
+ Do not put secrets in YAML committed to the repository, process arguments, or
181
+ logs.
182
+
183
+ Pin the RubyDB version and configuration for each deployment. Review changes to
184
+ durability mode, WAL retention, checkpoint thresholds, memory, connection
185
+ limits, request deadlines, lock timeouts, and TLS/authentication as production
186
+ changes. Keep a configuration checksum in the deployment record.
187
+
188
+ ## Readiness checklist
189
+
190
+ Before accepting traffic:
191
+
192
+ * database directory is on approved storage with sufficient space and inodes;
193
+ * service account and file permissions are verified;
194
+ * TLS certificate, key, CA, hostname, and expiration are checked;
195
+ * authentication and authorization deny an unauthenticated test client;
196
+ * health and readiness checks exercise a real request path;
197
+ * connection, request, lock, and shutdown timeouts are bounded;
198
+ * schema/migrations have completed and version/checksum is recorded;
199
+ * full backup has been created and restored into a fresh directory;
200
+ * monitoring, alert routing, and log retention are active;
201
+ * rollback and restore owners are named; and
202
+ * a representative smoke query and write have passed.
203
+
204
+ ## Capacity and resource limits
205
+
206
+ Set explicit limits for connections, request duration, lock waits, result size,
207
+ memory, worker count, WAL size, backup space, and file descriptors. Size the
208
+ application pool below the server limit, leaving room for migrations,
209
+ replication, health checks, and administration. A pool that equals the server
210
+ limit can starve the control plane.
211
+
212
+ Alert before exhaustion, not after it. Watch CPU, RSS, open files, disk bytes,
213
+ free inodes, WAL bytes, checkpoint age/duration, active transactions, lock
214
+ waits, pool utilization, errors, cancellations, and p95/p99 latency.
215
+
216
+ ## Backup policy
217
+
218
+ Define RPO and RTO with the application owner. At minimum, maintain verified
219
+ full backups, protect them from the database host, encrypt them at rest and in
220
+ transit, retain multiple generations, and record manifests/checksums. If using
221
+ incremental or differential backups, retain their verified base and ordered
222
+ chain.
223
+
224
+ A successful backup command is not proof of recoverability. Regularly restore
225
+ to an isolated directory, validate checksums and schema, run representative
226
+ queries, compare critical row counts, and record elapsed restore time. Run a
227
+ restore drill after format, backup, storage, or release changes.
228
+
229
+ ## Upgrade procedure
230
+
231
+ 1. Read the release notes, format compatibility, and migration notes.
232
+ 2. Create and verify a new full backup.
233
+ 3. Test the new version against a restored production-like copy.
234
+ 4. Run schema and application smoke tests, including populated-table writes.
235
+ 5. Drain or fence writes according to the deployment topology.
236
+ 6. Upgrade one controlled instance and verify health, WAL, and metrics.
237
+ 7. Re-enable traffic gradually and watch errors and latency.
238
+ 8. Keep the rollback binary and backup available until the validation window
239
+ closes.
240
+
241
+ Never roll back by pointing an older binary at a directory whose format or
242
+ metadata it cannot read. Use the documented restore/rollback path.
243
+
244
+ ## Failover procedure
245
+
246
+ RubyDB’s safe failover model requires a synchronized candidate and a durable
247
+ fencing decision. A manual operator sequence is:
248
+
249
+ 1. declare the incident and stop or isolate application writes;
250
+ 2. verify the primary’s last acknowledged LSN and fence epoch;
251
+ 3. confirm the candidate’s applied LSN and integrity;
252
+ 4. fence the old primary at the process, host, storage, or network layer;
253
+ 5. promote only after fencing is observable and durable;
254
+ 6. point clients at the new primary and run smoke writes/reads;
255
+ 7. monitor replication and stale-writer rejection; and
256
+ 8. recover the old primary as a replica only after its state is understood.
257
+
258
+ Automatic election requires an independently validated quorum, fencing,
259
+ partition behavior, stale-primary rejection, and recovery procedure. Do not
260
+ enable election based solely on a successful same-host test.
261
+
262
+ ## Incident response
263
+
264
+ Contain first: stop unsafe writes, protect the database directory, and record
265
+ the timeline. Preserve logs, metrics, WAL, metadata, configuration, process
266
+ state, and backup manifests. Use [troubleshooting](../troubleshooting.md) and
267
+ [debugging](../debugging.md) for evidence collection.
268
+
269
+ Classify the event as availability, durability, correctness, security, or
270
+ capacity. Assign an incident owner and a recovery owner. Communicate whether
271
+ commit outcomes are known, unknown, or confirmed rolled back. After recovery,
272
+ verify application invariants rather than relying only on process health.
273
+
274
+ ## TLS and secret rotation
275
+
276
+ Stage new certificates and CA material, validate the chain and hostname with a
277
+ test client, then switch through an atomic deployment/configuration change.
278
+ Maintain an overlap window only if clients support it. Confirm old material is
279
+ no longer accepted before revoking it. Rotate database passwords and peer
280
+ tokens through the secret manager; audit access and avoid printing values.
281
+
282
+ ## Maintenance
283
+
284
+ Schedule vacuum, compaction, checkpoint, index maintenance, and backups with
285
+ awareness of active readers and write load. Measure before and after. Use a
286
+ copy for repair or compaction experiments. Verify reopen, checksums, row counts,
287
+ indexes, and application smoke queries after maintenance.
288
+
289
+ ## Production evidence
290
+
291
+ The release record should contain the RubyDB commit, Ruby/Rails versions,
292
+ configuration checksum, schema/migration version, backup manifest, restore
293
+ drill result, benchmark/soak result, monitoring link, security review status,
294
+ and known limitations. See [production readiness](../production-readiness.md)
295
+ for the project-level boundaries.