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.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -15
- data/.github/workflows/benchmark.yml +26 -26
- data/.github/workflows/compatibility.yml +63 -63
- data/.github/workflows/fuzz.yml +33 -33
- data/.github/workflows/lint.yml +21 -21
- data/.github/workflows/operations.yml +24 -24
- data/.github/workflows/production-validation.yml +111 -111
- data/.github/workflows/release.yml +77 -77
- data/.github/workflows/security.yml +39 -37
- data/.github/workflows/test.yml +26 -26
- data/.github/workflows/workload.yml +58 -58
- data/.gitignore +16 -5
- data/.rubocop.yml +50 -44
- data/.standard.yml +9 -14
- data/ARCHITECTURE.md +21 -21
- data/CHANGELOG.md +57 -27
- data/CODE_OF_CONDUCT.md +13 -13
- data/CONTRIBUTING.md +29 -29
- data/GOVERNANCE.md +16 -16
- data/Gemfile +18 -17
- data/Gemfile.lock +125 -71
- data/README.md +168 -12
- data/ROADMAP.md +27 -27
- data/Rakefile +76 -71
- data/SECURITY.md +54 -54
- data/SUPPORT.md +14 -14
- data/accelerator/bin/SHA256SUMS +6 -0
- data/accelerator/bin/rubydb-accelerator-darwin-amd64 +0 -0
- data/accelerator/bin/rubydb-accelerator-darwin-arm64 +0 -0
- data/accelerator/bin/rubydb-accelerator-linux-amd64 +0 -0
- data/accelerator/bin/rubydb-accelerator-linux-arm64 +0 -0
- data/accelerator/bin/rubydb-accelerator-windows-amd64.exe +0 -0
- data/accelerator/bin/rubydb-accelerator-windows-arm64.exe +0 -0
- data/accelerator/cmd/rubydb-accelerator/main.go +11 -0
- data/accelerator/go.mod +3 -0
- data/accelerator/internal/execution/aggregate.go +94 -0
- data/accelerator/internal/execution/distinct.go +22 -0
- data/accelerator/internal/execution/filter.go +73 -0
- data/accelerator/internal/execution/join.go +79 -0
- data/accelerator/internal/execution/operators.go +167 -0
- data/accelerator/internal/execution/scan.go +20 -0
- data/accelerator/internal/execution/sort.go +62 -0
- data/accelerator/internal/execution/types.go +136 -0
- data/accelerator/internal/execution/value.go +67 -0
- data/accelerator/internal/memory/arena.go +47 -0
- data/accelerator/internal/memory/reuse.go +22 -0
- data/accelerator/internal/metrics/registry.go +67 -0
- data/accelerator/internal/parallel/bounded_queue.go +56 -0
- data/accelerator/internal/parallel/scheduler.go +47 -0
- data/accelerator/internal/parallel/worker_pool.go +53 -0
- data/accelerator/internal/protocol/cancellation.go +48 -0
- data/accelerator/internal/protocol/columnar.go +263 -0
- data/accelerator/internal/protocol/frame.go +187 -0
- data/accelerator/internal/runtime/worker.go +521 -0
- data/accelerator/internal/storage/page_reader.go +81 -0
- data/accelerator/internal/storage/snapshot_scan.go +539 -0
- data/accelerator/internal/wal/checksum.go +13 -0
- data/accelerator/internal/wal/compression.go +41 -0
- data/accelerator/internal/wal/group_commit.go +24 -0
- data/accelerator/internal/wal/record_encoder.go +40 -0
- data/adapters/activerecord/Gemfile +11 -11
- data/adapters/activerecord/README.md +8 -3
- data/adapters/activerecord/lib/active_record/connection_adapters/rubydb_adapter.rb +881 -879
- data/adapters/activerecord/rubydb-activerecord.gemspec +21 -21
- data/adapters/activerecord/spec/rubydb_adapter_integration_spec.rb +143 -143
- data/adapters/ruby/README.md +18 -18
- data/adapters/sequel/README.md +11 -11
- data/config/monitoring/prometheus-alerts.yml +39 -39
- data/config/production.yml +36 -36
- data/docs/README.md +77 -71
- data/docs/architecture/concurrency.md +14 -14
- data/docs/architecture/current-state.md +125 -125
- data/docs/architecture/execution-engine.md +25 -25
- data/docs/architecture/go-accelerator.md +179 -0
- data/docs/architecture/indexes.md +19 -19
- data/docs/architecture/mvcc.md +19 -19
- data/docs/architecture/overview.md +13 -13
- data/docs/architecture/pages.md +11 -11
- data/docs/architecture/production-roadmap.md +82 -82
- data/docs/architecture/query-planner.md +20 -20
- data/docs/architecture/recovery.md +18 -18
- data/docs/architecture/sql-engine.md +12 -12
- data/docs/architecture/storage-engine.md +14 -14
- data/docs/architecture/transactions.md +10 -10
- data/docs/architecture/wal.md +28 -28
- data/docs/cli-cheatsheet.md +98 -98
- data/docs/cli.md +299 -275
- data/docs/contributing/architecture.md +9 -9
- data/docs/contributing/benchmarking.md +30 -14
- data/docs/contributing/development.md +16 -16
- data/docs/contributing/release-process.md +49 -49
- data/docs/contributing/testing.md +16 -16
- data/docs/debugging.md +229 -229
- data/docs/developer/branching.md +10 -10
- data/docs/developer/database-diff.md +10 -10
- data/docs/developer/local-development.md +49 -17
- data/docs/developer/snapshots.md +9 -9
- data/docs/developer/temporal-data.md +10 -10
- data/docs/developer-guide.md +297 -297
- data/docs/getting-started/first-database.md +16 -16
- data/docs/getting-started/first-query.md +13 -13
- data/docs/getting-started/installation.md +19 -19
- data/docs/getting-started/local-to-production.md +300 -300
- data/docs/getting-started/quickstart.md +17 -17
- data/docs/getting-started/rails.md +16 -16
- data/docs/hardening_backlog.md +93 -93
- data/docs/lessons-learned.md +112 -112
- data/docs/operations/backups.md +33 -33
- data/docs/operations/disaster-recovery.md +31 -31
- data/docs/operations/failover.md +30 -30
- data/docs/operations/monitoring.md +25 -25
- data/docs/operations/production-guide.md +295 -295
- data/docs/operations/production-runbook.md +45 -45
- data/docs/operations/replication.md +33 -33
- data/docs/operations/restore.md +6 -6
- data/docs/operations/runbook.md +34 -34
- data/docs/operations/upgrades.md +14 -14
- data/docs/operations/workload-testing.md +17 -17
- data/docs/production-readiness.md +118 -118
- data/docs/production_validation.md +150 -150
- data/docs/rails/active-record.md +11 -11
- data/docs/rails/compatibility-guide.md +90 -90
- data/docs/rails/database-yml.md +92 -92
- data/docs/rails/installation.md +17 -17
- data/docs/rails/migrations.md +17 -17
- data/docs/rails/production.md +82 -82
- data/docs/rails/troubleshooting.md +18 -18
- data/docs/release.md +25 -25
- data/docs/server/architecture.md +10 -10
- data/docs/server/authentication.md +10 -10
- data/docs/server/configuration.md +16 -16
- data/docs/server/connection-pooling.md +10 -10
- data/docs/server/deployment.md +10 -10
- data/docs/server/protocol.md +12 -12
- data/docs/sql/compatibility-guide.md +82 -82
- data/docs/sql/compatibility.md +39 -39
- data/docs/sql/data-types.md +10 -10
- data/docs/sql/functions.md +9 -9
- data/docs/sql/joins.md +9 -9
- data/docs/sql/operators.md +9 -9
- data/docs/sql/sqlite-compatibility.md +21 -21
- data/docs/sql/syntax.md +10 -10
- data/docs/sql/transactions.md +10 -10
- data/docs/troubleshooting.md +244 -244
- data/lessons/01-foundations.md +73 -0
- data/lessons/02-local-development.md +121 -0
- data/lessons/03-embedded-rubydb.md +99 -0
- data/lessons/04-rails-complex-apps.md +138 -0
- data/lessons/05-rubydb-production-server.md +237 -0
- data/lessons/06-postgresql-massive-apps.md +96 -0
- data/lessons/07-hybrid-microservices.md +179 -0
- data/lessons/08-migrations-backups-recovery.md +86 -0
- data/lessons/09-observability-security-scale.md +87 -0
- data/lessons/10-release-readiness.md +192 -0
- data/lessons/11-community-adapter.md +323 -0
- data/lessons/12-rails-ecommerce-pressure.md +263 -0
- data/lib/rubydb/accelerator/client.rb +451 -0
- data/lib/rubydb/accelerator/error.rb +22 -0
- data/lib/rubydb/accelerator/manager.rb +606 -0
- data/lib/rubydb/accelerator.rb +13 -0
- data/lib/rubydb/backup/archive.rb +332 -334
- data/lib/rubydb/backup/backup.rb +400 -401
- data/lib/rubydb/backup/incremental.rb +349 -353
- data/lib/rubydb/backup/restore.rb +289 -290
- data/lib/rubydb/backup/snapshot.rb +265 -267
- data/lib/rubydb/backup/verification.rb +276 -279
- data/lib/rubydb/branching/branch.rb +181 -181
- data/lib/rubydb/branching/branch_manager.rb +307 -311
- data/lib/rubydb/branching/branch_metadata.rb +140 -140
- data/lib/rubydb/branching/checkout.rb +165 -166
- data/lib/rubydb/branching/copy_on_write.rb +272 -272
- data/lib/rubydb/branching/diff.rb +137 -138
- data/lib/rubydb/branching/merge.rb +282 -285
- data/lib/rubydb/build_info.rb +15 -15
- data/lib/rubydb/catalog/catalog.rb +391 -391
- data/lib/rubydb/catalog/column.rb +112 -112
- data/lib/rubydb/catalog/constraint.rb +180 -180
- data/lib/rubydb/catalog/database.rb +184 -184
- data/lib/rubydb/catalog/index.rb +97 -97
- data/lib/rubydb/catalog/schema.rb +103 -103
- data/lib/rubydb/catalog/sequence.rb +90 -90
- data/lib/rubydb/catalog/system_catalog.rb +698 -698
- data/lib/rubydb/catalog/table.rb +178 -178
- data/lib/rubydb/catalog/trigger.rb +102 -102
- data/lib/rubydb/catalog/view.rb +66 -66
- data/lib/rubydb/cli/application.rb +168 -163
- data/lib/rubydb/cli/commands/accelerator.rb +72 -0
- data/lib/rubydb/cli/commands/backup.rb +80 -81
- data/lib/rubydb/cli/commands/branch.rb +72 -72
- data/lib/rubydb/cli/commands/checkout.rb +54 -54
- data/lib/rubydb/cli/commands/create.rb +58 -58
- data/lib/rubydb/cli/commands/diff.rb +76 -77
- data/lib/rubydb/cli/commands/doctor.rb +77 -74
- data/lib/rubydb/cli/commands/drop.rb +57 -57
- data/lib/rubydb/cli/commands/init.rb +101 -102
- data/lib/rubydb/cli/commands/inspect.rb +95 -95
- data/lib/rubydb/cli/commands/merge.rb +63 -63
- data/lib/rubydb/cli/commands/migrate.rb +62 -62
- data/lib/rubydb/cli/commands/restart.rb +42 -39
- data/lib/rubydb/cli/commands/restore.rb +121 -121
- data/lib/rubydb/cli/commands/shell.rb +365 -365
- data/lib/rubydb/cli/commands/snapshot.rb +79 -79
- data/lib/rubydb/cli/commands/start.rb +88 -82
- data/lib/rubydb/cli/commands/status.rb +96 -92
- data/lib/rubydb/cli/commands/stop.rb +47 -47
- data/lib/rubydb/cli/commands/vacuum.rb +58 -58
- data/lib/rubydb/cli/formatter.rb +221 -221
- data/lib/rubydb/cli/output.rb +168 -168
- data/lib/rubydb/client/client.rb +309 -304
- data/lib/rubydb/client/connection.rb +429 -415
- data/lib/rubydb/client/connection_pool.rb +168 -168
- data/lib/rubydb/client/connection_url.rb +96 -96
- data/lib/rubydb/client/prepared_statement.rb +60 -60
- data/lib/rubydb/client/result.rb +127 -123
- data/lib/rubydb/client/statement.rb +52 -52
- data/lib/rubydb/client/transaction.rb +130 -130
- data/lib/rubydb/concurrency/concurrency.rb +19 -19
- data/lib/rubydb/concurrency/deadlock_detector.rb +148 -150
- data/lib/rubydb/concurrency/latch.rb +101 -101
- data/lib/rubydb/concurrency/lock_graph.rb +163 -165
- data/lib/rubydb/concurrency/mutex.rb +181 -183
- data/lib/rubydb/concurrency/rw_lock.rb +180 -180
- data/lib/rubydb/concurrency/scheduler.rb +248 -250
- data/lib/rubydb/concurrency/worker_pool.rb +145 -143
- data/lib/rubydb/configuration/config.rb +170 -170
- data/lib/rubydb/configuration/defaults.rb +191 -179
- data/lib/rubydb/configuration/environment.rb +152 -152
- data/lib/rubydb/configuration/parser.rb +185 -185
- data/lib/rubydb/configuration/validation.rb +228 -221
- data/lib/rubydb/constants.rb +74 -74
- data/lib/rubydb/constraints/check.rb +181 -181
- data/lib/rubydb/constraints/constraint.rb +101 -101
- data/lib/rubydb/constraints/foreign_key.rb +130 -130
- data/lib/rubydb/constraints/not_null.rb +64 -64
- data/lib/rubydb/constraints/primary_key.rb +99 -99
- data/lib/rubydb/constraints/unique.rb +106 -108
- data/lib/rubydb/constraints/validator.rb +349 -350
- data/lib/rubydb/errors/authentication_error.rb +10 -10
- data/lib/rubydb/errors/authorization_error.rb +23 -23
- data/lib/rubydb/errors/client_error.rb +10 -10
- data/lib/rubydb/errors/configuration_error.rb +10 -10
- data/lib/rubydb/errors/connection_error.rb +10 -10
- data/lib/rubydb/errors/constraint_error.rb +23 -23
- data/lib/rubydb/errors/corruption_error.rb +10 -10
- data/lib/rubydb/errors/database_error.rb +10 -10
- data/lib/rubydb/errors/error.rb +20 -20
- data/lib/rubydb/errors/execution_error.rb +10 -10
- data/lib/rubydb/errors/parser_error.rb +10 -10
- data/lib/rubydb/errors/recovery_error.rb +10 -10
- data/lib/rubydb/errors/replication_error.rb +10 -10
- data/lib/rubydb/errors/server_error.rb +6 -6
- data/lib/rubydb/errors/storage_error.rb +10 -10
- data/lib/rubydb/errors/transaction_error.rb +10 -10
- data/lib/rubydb/execution/accelerator_dispatch.rb +30 -0
- data/lib/rubydb/execution/aggregate_executor.rb +134 -138
- data/lib/rubydb/execution/cost_model.rb +72 -0
- data/lib/rubydb/execution/delete_executor.rb +110 -112
- data/lib/rubydb/execution/distinct_executor.rb +131 -135
- data/lib/rubydb/execution/executor.rb +1544 -1188
- data/lib/rubydb/execution/expression.rb +191 -193
- data/lib/rubydb/execution/index_scan.rb +142 -142
- data/lib/rubydb/execution/insert_executor.rb +215 -217
- data/lib/rubydb/execution/join_executor.rb +243 -249
- data/lib/rubydb/execution/limit_executor.rb +83 -85
- data/lib/rubydb/execution/operator_selection.rb +57 -0
- data/lib/rubydb/execution/optimizer.rb +227 -215
- data/lib/rubydb/execution/physical_plan.rb +47 -0
- data/lib/rubydb/execution/plan.rb +355 -353
- data/lib/rubydb/execution/planner.rb +508 -536
- data/lib/rubydb/execution/predicate.rb +235 -235
- data/lib/rubydb/execution/scan.rb +49 -49
- data/lib/rubydb/execution/sequential_scan.rb +63 -63
- data/lib/rubydb/execution/sort_executor.rb +194 -185
- data/lib/rubydb/execution/update_executor.rb +160 -162
- data/lib/rubydb/functions/aggregate.rb +70 -70
- data/lib/rubydb/functions/date_functions.rb +274 -278
- data/lib/rubydb/functions/function.rb +85 -85
- data/lib/rubydb/functions/json_functions.rb +231 -215
- data/lib/rubydb/functions/numeric_functions.rb +346 -346
- data/lib/rubydb/functions/scalar.rb +52 -52
- data/lib/rubydb/functions/string_functions.rb +383 -383
- data/lib/rubydb/functions/system_functions.rb +258 -246
- data/lib/rubydb/history/as_of.rb +238 -238
- data/lib/rubydb/history/change.rb +105 -105
- data/lib/rubydb/history/history.rb +131 -131
- data/lib/rubydb/history/history_manager.rb +228 -229
- data/lib/rubydb/history/temporal_query.rb +202 -202
- data/lib/rubydb/history/timeline.rb +144 -144
- data/lib/rubydb/indexes/btree.rb +215 -186
- data/lib/rubydb/indexes/btree_cursor.rb +258 -258
- data/lib/rubydb/indexes/btree_node.rb +384 -385
- data/lib/rubydb/indexes/hash_index.rb +150 -150
- data/lib/rubydb/indexes/index.rb +71 -71
- data/lib/rubydb/indexes/index_manager.rb +408 -406
- data/lib/rubydb/indexes/index_scan.rb +466 -470
- data/lib/rubydb/migrations/migration.rb +253 -254
- data/lib/rubydb/migrations/migration_lock.rb +146 -146
- data/lib/rubydb/migrations/migration_manager.rb +187 -176
- data/lib/rubydb/migrations/migration_version.rb +71 -71
- data/lib/rubydb/migrations/schema_diff.rb +211 -211
- data/lib/rubydb/migrations/schema_version.rb +64 -64
- data/lib/rubydb/monitoring/events.rb +155 -160
- data/lib/rubydb/monitoring/health.rb +216 -222
- data/lib/rubydb/monitoring/logger.rb +188 -193
- data/lib/rubydb/monitoring/metrics.rb +363 -359
- data/lib/rubydb/monitoring/performance.rb +176 -176
- data/lib/rubydb/monitoring/statistics.rb +168 -170
- data/lib/rubydb/mvcc/garbage_collector.rb +199 -199
- data/lib/rubydb/mvcc/mvcc.rb +16 -16
- data/lib/rubydb/mvcc/snapshot.rb +146 -147
- data/lib/rubydb/mvcc/vacuum.rb +180 -180
- data/lib/rubydb/mvcc/version.rb +106 -106
- data/lib/rubydb/mvcc/version_store.rb +396 -398
- data/lib/rubydb/mvcc/visibility.rb +107 -109
- data/lib/rubydb/protocol/capabilities.rb +125 -125
- data/lib/rubydb/protocol/decoder.rb +142 -145
- data/lib/rubydb/protocol/encoder.rb +131 -136
- data/lib/rubydb/protocol/handshake.rb +306 -305
- data/lib/rubydb/protocol/message.rb +121 -121
- data/lib/rubydb/protocol/parameter_binder.rb +101 -0
- data/lib/rubydb/protocol/protocol.rb +276 -277
- data/lib/rubydb/protocol/version.rb +54 -54
- data/lib/rubydb/rails/adapter.rb +245 -239
- data/lib/rubydb/rails/connection.rb +312 -314
- data/lib/rubydb/rails/database_statements.rb +122 -122
- data/lib/rubydb/rails/migration.rb +131 -131
- data/lib/rubydb/rails/quoting.rb +109 -109
- data/lib/rubydb/rails/result.rb +117 -117
- data/lib/rubydb/rails/schema_statements.rb +339 -339
- data/lib/rubydb/rails/transaction.rb +105 -105
- data/lib/rubydb/rails/type.rb +126 -126
- data/lib/rubydb/recovery/checkpoint.rb +261 -257
- data/lib/rubydb/recovery/consistency.rb +457 -467
- data/lib/rubydb/recovery/corruption_detector.rb +5 -5
- data/lib/rubydb/recovery/crash_recovery.rb +381 -387
- data/lib/rubydb/recovery/recovery_manager.rb +204 -206
- data/lib/rubydb/recovery/redo.rb +235 -237
- data/lib/rubydb/recovery/undo.rb +204 -206
- data/lib/rubydb/replication/failover.rb +5 -5
- data/lib/rubydb/replication/fencing.rb +63 -63
- data/lib/rubydb/replication/primary.rb +461 -450
- data/lib/rubydb/replication/replica.rb +382 -384
- data/lib/rubydb/replication/replication_log.rb +194 -200
- data/lib/rubydb/replication/replication_manager.rb +307 -308
- data/lib/rubydb/replication/replication_slot.rb +293 -295
- data/lib/rubydb/replication/replication_stream.rb +198 -201
- data/lib/rubydb/rubydb.rb +570 -560
- data/lib/rubydb/security/access_control.rb +252 -254
- data/lib/rubydb/security/audit_log.rb +209 -213
- data/lib/rubydb/security/authentication.rb +302 -302
- data/lib/rubydb/security/authorization.rb +282 -282
- data/lib/rubydb/security/credentials.rb +192 -196
- data/lib/rubydb/security/password.rb +205 -215
- data/lib/rubydb/security/permissions.rb +74 -74
- data/lib/rubydb/security/role.rb +99 -101
- data/lib/rubydb/security/user.rb +86 -86
- data/lib/rubydb/server/connection.rb +383 -366
- data/lib/rubydb/server/connection_pool.rb +193 -193
- data/lib/rubydb/server/lifecycle.rb +227 -228
- data/lib/rubydb/server/listener.rb +139 -136
- data/lib/rubydb/server/request_handler.rb +277 -276
- data/lib/rubydb/server/server.rb +363 -364
- data/lib/rubydb/server/session.rb +416 -369
- data/lib/rubydb/server/worker.rb +206 -210
- data/lib/rubydb/server/worker_pool.rb +168 -168
- data/lib/rubydb/sql/ast/alter_table.rb +169 -169
- data/lib/rubydb/sql/ast/begin_transaction.rb +47 -47
- data/lib/rubydb/sql/ast/commit.rb +37 -37
- data/lib/rubydb/sql/ast/constraint.rb +92 -83
- data/lib/rubydb/sql/ast/create_database.rb +41 -41
- data/lib/rubydb/sql/ast/create_index.rb +61 -61
- data/lib/rubydb/sql/ast/create_schema.rb +52 -52
- data/lib/rubydb/sql/ast/create_table.rb +187 -187
- data/lib/rubydb/sql/ast/delete.rb +54 -54
- data/lib/rubydb/sql/ast/drop_database.rb +41 -41
- data/lib/rubydb/sql/ast/drop_index.rb +41 -41
- data/lib/rubydb/sql/ast/drop_schema.rb +49 -49
- data/lib/rubydb/sql/ast/drop_table.rb +49 -49
- data/lib/rubydb/sql/ast/explain.rb +64 -64
- data/lib/rubydb/sql/ast/expression.rb +617 -604
- data/lib/rubydb/sql/ast/insert.rb +66 -66
- data/lib/rubydb/sql/ast/node.rb +42 -42
- data/lib/rubydb/sql/ast/rollback.rb +63 -63
- data/lib/rubydb/sql/ast/savepoint.rb +59 -59
- data/lib/rubydb/sql/ast/select.rb +88 -88
- data/lib/rubydb/sql/ast/set_operation.rb +22 -20
- data/lib/rubydb/sql/ast/trigger.rb +35 -29
- data/lib/rubydb/sql/ast/update.rb +88 -88
- data/lib/rubydb/sql/ast/vacuum.rb +19 -19
- data/lib/rubydb/sql/ast/view.rb +38 -32
- data/lib/rubydb/sql/ast/with.rb +32 -32
- data/lib/rubydb/sql/grammar.rb +86 -86
- data/lib/rubydb/sql/keywords.rb +156 -156
- data/lib/rubydb/sql/lexer.rb +209 -214
- data/lib/rubydb/sql/operators.rb +100 -100
- data/lib/rubydb/sql/parser.rb +1167 -1170
- data/lib/rubydb/sql/planner/analyzer.rb +283 -302
- data/lib/rubydb/sql/planner/binder.rb +537 -550
- data/lib/rubydb/sql/planner/type_checker.rb +427 -431
- data/lib/rubydb/sql/token.rb +210 -210
- data/lib/rubydb/storage/buffer_frame.rb +44 -44
- data/lib/rubydb/storage/buffer_pool.rb +155 -155
- data/lib/rubydb/storage/database_lock.rb +74 -74
- data/lib/rubydb/storage/deserializer.rb +332 -342
- data/lib/rubydb/storage/engine.rb +2409 -2330
- data/lib/rubydb/storage/file_manager.rb +191 -187
- data/lib/rubydb/storage/free_space_map.rb +79 -81
- data/lib/rubydb/storage/page.rb +92 -94
- data/lib/rubydb/storage/page_allocator.rb +852 -855
- data/lib/rubydb/storage/page_header.rb +63 -67
- data/lib/rubydb/storage/page_manager.rb +127 -131
- data/lib/rubydb/storage/record.rb +58 -58
- data/lib/rubydb/storage/row.rb +78 -78
- data/lib/rubydb/storage/serializer.rb +51 -51
- data/lib/rubydb/storage/snapshot_reader.rb +167 -0
- data/lib/rubydb/storage/storage_layout.rb +151 -151
- data/lib/rubydb/storage/storage_manager.rb +114 -114
- data/lib/rubydb/storage/tuple.rb +458 -461
- data/lib/rubydb/storage/visibility_map.rb +964 -973
- data/lib/rubydb/transactions/commit_manager.rb +219 -220
- data/lib/rubydb/transactions/isolation.rb +98 -98
- data/lib/rubydb/transactions/lock.rb +76 -76
- data/lib/rubydb/transactions/lock_manager.rb +359 -362
- data/lib/rubydb/transactions/savepoint.rb +142 -143
- data/lib/rubydb/transactions/transaction.rb +214 -215
- data/lib/rubydb/transactions/transaction_id.rb +84 -84
- data/lib/rubydb/transactions/transaction_log.rb +256 -257
- data/lib/rubydb/transactions/transaction_manager.rb +434 -435
- data/lib/rubydb/types/bigint.rb +36 -36
- data/lib/rubydb/types/blob.rb +37 -37
- data/lib/rubydb/types/boolean.rb +34 -34
- data/lib/rubydb/types/date.rb +39 -39
- data/lib/rubydb/types/decimal.rb +48 -48
- data/lib/rubydb/types/float.rb +34 -34
- data/lib/rubydb/types/integer.rb +36 -36
- data/lib/rubydb/types/json.rb +41 -41
- data/lib/rubydb/types/null.rb +34 -34
- data/lib/rubydb/types/smallint.rb +36 -36
- data/lib/rubydb/types/text.rb +37 -37
- data/lib/rubydb/types/time.rb +46 -46
- data/lib/rubydb/types/timestamp.rb +39 -39
- data/lib/rubydb/types/type.rb +119 -119
- data/lib/rubydb/types/uuid.rb +47 -47
- data/lib/rubydb/types/varchar.rb +37 -37
- data/lib/rubydb/version.rb +32 -32
- data/lib/rubydb/wal/archive.rb +207 -193
- data/lib/rubydb/wal/checkpoint.rb +181 -183
- data/lib/rubydb/wal/lsn.rb +94 -94
- data/lib/rubydb/wal/reader.rb +259 -260
- data/lib/rubydb/wal/record.rb +105 -105
- data/lib/rubydb/wal/segment.rb +193 -193
- data/lib/rubydb/wal/wal.rb +481 -452
- data/lib/rubydb/wal/writer.rb +236 -236
- data/lib/rubydb.rb +7 -7
- data/packaging/docker/docker-compose.failover.yml +43 -43
- data/packaging/homebrew/rubydb.rb +19 -19
- data/rubydb.gemspec +70 -57
- data/scripts/benchmark +7 -7
- data/scripts/build_accelerator +49 -0
- data/scripts/durability_drill +37 -37
- data/scripts/fuzz +63 -63
- data/scripts/release +77 -42
- data/scripts/release_check +43 -43
- data/scripts/replication_failover_drill +268 -250
- data/scripts/replication_network_failover_drill +287 -255
- data/scripts/restore_drill +45 -45
- data/scripts/security +45 -0
- metadata +102 -1
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
# Installation
|
|
2
|
-
|
|
3
|
-
RubyDB requires Ruby 3.3 or newer in the current support policy.
|
|
4
|
-
|
|
5
|
-
```sh
|
|
6
|
-
gem install rubydb --pre
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
From a checkout:
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
bundle install
|
|
13
|
-
bundle exec rspec
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
For Rails, install the adapter from `adapters/activerecord` and use the
|
|
17
|
-
configuration documented in `docs/rails/database-yml.md`. Pin RubyDB and Ruby
|
|
18
|
-
versions in production and test the exact gem on a restored staging backup
|
|
19
|
-
before deployment.
|
|
1
|
+
# Installation
|
|
2
|
+
|
|
3
|
+
RubyDB requires Ruby 3.3 or newer in the current support policy.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
gem install rubydb --pre
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
From a checkout:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
bundle install
|
|
13
|
+
bundle exec rspec
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
For Rails, install the adapter from `adapters/activerecord` and use the
|
|
17
|
+
configuration documented in `docs/rails/database-yml.md`. Pin RubyDB and Ruby
|
|
18
|
+
versions in production and test the exact gem on a restored staging backup
|
|
19
|
+
before deployment.
|
|
@@ -1,300 +1,300 @@
|
|
|
1
|
-
# From local development to production
|
|
2
|
-
|
|
3
|
-
This guide is for a beginner starting with a Ruby or Rails application. It
|
|
4
|
-
shows two valid deployment choices:
|
|
5
|
-
|
|
6
|
-
1. develop with RubyDB locally and deploy with PostgreSQL; or
|
|
7
|
-
2. develop with RubyDB locally and keep RubyDB in production.
|
|
8
|
-
|
|
9
|
-
The application code can be similar in both cases, but the database is not
|
|
10
|
-
interchangeable by copying files. Choose the production database before
|
|
11
|
-
launch, run the application’s migrations and query tests against it, and make
|
|
12
|
-
backups before importing important data.
|
|
13
|
-
|
|
14
|
-
## Which path should I choose?
|
|
15
|
-
|
|
16
|
-
| Goal | Local database | Production database | Recommended when |
|
|
17
|
-
| --- | --- | --- | --- |
|
|
18
|
-
| Learn/build quickly | RubyDB embedded | PostgreSQL | You want the broadest hosting and Rails ecosystem |
|
|
19
|
-
| Keep one Ruby-native database | RubyDB embedded | RubyDB server | Your SQL/workload fits RubyDB and you can operate the server |
|
|
20
|
-
| Prototype only | RubyDB embedded | RubyDB embedded | One process owns the path and data is non-critical |
|
|
21
|
-
|
|
22
|
-
For a public or business-critical application, PostgreSQL is the safer default
|
|
23
|
-
until RubyDB has been validated against your complete workload, backup/restore
|
|
24
|
-
process, concurrency, and failover requirements. RubyDB is not a complete
|
|
25
|
-
PostgreSQL or SQLite replacement.
|
|
26
|
-
|
|
27
|
-
## Part 1: local Rails development with RubyDB
|
|
28
|
-
|
|
29
|
-
### 1. Add the gems
|
|
30
|
-
|
|
31
|
-
In the Rails application `Gemfile`:
|
|
32
|
-
|
|
33
|
-
```ruby
|
|
34
|
-
gem "rubydb"
|
|
35
|
-
gem "rubydb-activerecord"
|
|
36
|
-
gem "pg" # Keep this if PostgreSQL is a possible production target.
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Run:
|
|
40
|
-
|
|
41
|
-
```sh
|
|
42
|
-
bundle install
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### 2. Configure development and test
|
|
46
|
-
|
|
47
|
-
Use an embedded path for local development. Only the Rails process should own
|
|
48
|
-
each path:
|
|
49
|
-
|
|
50
|
-
```yaml
|
|
51
|
-
default: &default
|
|
52
|
-
adapter: rubydb
|
|
53
|
-
embedded: true
|
|
54
|
-
database: <%= Rails.root.join("tmp/rubydb_development.rdb") %>
|
|
55
|
-
pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
|
|
56
|
-
|
|
57
|
-
development:
|
|
58
|
-
<<: *default
|
|
59
|
-
|
|
60
|
-
test:
|
|
61
|
-
<<: *default
|
|
62
|
-
database: <%= Rails.root.join("tmp/rubydb_test.rdb") %>
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Use separate development and test paths. Do not put the database under a
|
|
66
|
-
source-controlled directory. Do not let a web server, job worker, and console
|
|
67
|
-
open the same embedded path at the same time.
|
|
68
|
-
|
|
69
|
-
### 3. Create the schema and run the app
|
|
70
|
-
|
|
71
|
-
```sh
|
|
72
|
-
bin/rails db:create
|
|
73
|
-
bin/rails db:migrate
|
|
74
|
-
bin/rails db:seed # only if your seed data is safe to recreate
|
|
75
|
-
bin/rails test
|
|
76
|
-
bin/rails server
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Exercise real application flows: sign-up, login, CRUD, joins, eager loading,
|
|
80
|
-
background jobs, file metadata, transactions, and error handling. Do not test
|
|
81
|
-
only that the server boots.
|
|
82
|
-
|
|
83
|
-
### 4. Use RubyDB in a regular Ruby app
|
|
84
|
-
|
|
85
|
-
Local single-process code can use the embedded engine:
|
|
86
|
-
|
|
87
|
-
```ruby
|
|
88
|
-
require "rubydb"
|
|
89
|
-
|
|
90
|
-
engine = RubyDB::Storage::Engine.new("tmp/app.rdb")
|
|
91
|
-
begin
|
|
92
|
-
engine.execute("CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY, name TEXT)")
|
|
93
|
-
engine.execute("INSERT INTO events (name) VALUES (?)", ["boot"])
|
|
94
|
-
p engine.execute("SELECT * FROM events")
|
|
95
|
-
ensure
|
|
96
|
-
engine.close
|
|
97
|
-
end
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
For multiple processes, use the client/server connection described below.
|
|
101
|
-
|
|
102
|
-
## Part 2A: deploy the same app on PostgreSQL
|
|
103
|
-
|
|
104
|
-
This path keeps RubyDB for local development and uses PostgreSQL in production.
|
|
105
|
-
It is a database migration, not a file copy.
|
|
106
|
-
|
|
107
|
-
### 1. Configure the production Rails block
|
|
108
|
-
|
|
109
|
-
```yaml
|
|
110
|
-
production:
|
|
111
|
-
adapter: postgresql
|
|
112
|
-
url: <%= ENV.fetch("DATABASE_URL") %>
|
|
113
|
-
pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
The hosting provider supplies a PostgreSQL URL such as:
|
|
117
|
-
|
|
118
|
-
```text
|
|
119
|
-
postgresql://app_user:password@postgres.example.com:5432/my_app
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Keep `DATABASE_URL` in the provider’s secret settings. Never commit it.
|
|
123
|
-
|
|
124
|
-
### 2. Review the schema and SQL
|
|
125
|
-
|
|
126
|
-
Before switching, review RubyDB-specific behavior:
|
|
127
|
-
|
|
128
|
-
* integer primary-key/autoincrement behavior;
|
|
129
|
-
* `BOOLEAN`, `JSON`, `UUID`, dates, timestamps, and decimals;
|
|
130
|
-
* indexes, foreign keys, check constraints, and defaults;
|
|
131
|
-
* `NULL`, ordering, grouping, joins, upserts, and functions;
|
|
132
|
-
* migrations that alter populated tables; and
|
|
133
|
-
* raw SQL, extensions, pragmas, and database-specific functions.
|
|
134
|
-
|
|
135
|
-
Run `db:schema:dump` and inspect the generated schema. Do not assume every
|
|
136
|
-
RubyDB schema statement is valid PostgreSQL syntax. Fix migrations or use
|
|
137
|
-
adapter-specific migrations deliberately and document the difference.
|
|
138
|
-
|
|
139
|
-
### 3. Transfer data safely
|
|
140
|
-
|
|
141
|
-
RubyDB `.rdb` files cannot be opened by PostgreSQL. A safe small-dataset flow is:
|
|
142
|
-
|
|
143
|
-
1. stop writes to the RubyDB application;
|
|
144
|
-
2. create a verified RubyDB backup;
|
|
145
|
-
3. create the PostgreSQL database and run reviewed migrations;
|
|
146
|
-
4. export each table in a deterministic order, including parent tables first;
|
|
147
|
-
5. transform types and IDs explicitly;
|
|
148
|
-
6. import into PostgreSQL using bound/escaped data or PostgreSQL `COPY`;
|
|
149
|
-
7. compare row counts, checksums, foreign keys, indexes, and business totals;
|
|
150
|
-
8. run the application test and smoke suite against PostgreSQL; and
|
|
151
|
-
9. switch traffic only after the verification report is approved.
|
|
152
|
-
|
|
153
|
-
For large or live data, use a purpose-built migration process with checkpoints,
|
|
154
|
-
retries, idempotency, and a cutover plan. Do not write a one-off script that
|
|
155
|
-
silently skips a row or converts an unknown type to text.
|
|
156
|
-
|
|
157
|
-
### 4. Test production configuration before cutover
|
|
158
|
-
|
|
159
|
-
```sh
|
|
160
|
-
RAILS_ENV=production DATABASE_URL='postgresql://...' bin/rails db:migrate
|
|
161
|
-
RAILS_ENV=production DATABASE_URL='postgresql://...' bin/rails db:seed
|
|
162
|
-
RAILS_ENV=production DATABASE_URL='postgresql://...' bin/rails test
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Run this against a restored staging database, not the only production copy.
|
|
166
|
-
Keep the RubyDB backup until PostgreSQL row counts and application behavior
|
|
167
|
-
have been accepted.
|
|
168
|
-
|
|
169
|
-
## Part 2B: deploy RubyDB in production
|
|
170
|
-
|
|
171
|
-
This path runs one managed RubyDB server and connects Rails/Ruby processes to it
|
|
172
|
-
over the RubyDB protocol. The application never opens the server’s data file.
|
|
173
|
-
|
|
174
|
-
### 1. Provision a database host
|
|
175
|
-
|
|
176
|
-
Install a pinned RubyDB release, create a dedicated service account, and attach
|
|
177
|
-
persistent storage. The data directory must survive process restarts and
|
|
178
|
-
deploys. Keep backups on a separate system or failure domain.
|
|
179
|
-
|
|
180
|
-
```sh
|
|
181
|
-
gem install rubydb -v 0.1.0
|
|
182
|
-
install -d -o rubydb -g rubydb -m 0700 /var/lib/rubydb/data
|
|
183
|
-
install -d -o rubydb -g rubydb -m 0750 /var/log/rubydb
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
Use the complete setup in the [production operations guide](../operations/production-guide.md)
|
|
187
|
-
for service supervision, TLS, authentication, resource limits, backups, and
|
|
188
|
-
monitoring.
|
|
189
|
-
|
|
190
|
-
### 2. Start the RubyDB server
|
|
191
|
-
|
|
192
|
-
Use a reviewed production configuration with WAL, authentication, TLS, and
|
|
193
|
-
bounded resources:
|
|
194
|
-
|
|
195
|
-
```sh
|
|
196
|
-
rubydb --config /etc/rubydb/production.yml --env production start
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
Keep port `7432` on a private network. Verify the server before connecting the
|
|
200
|
-
application:
|
|
201
|
-
|
|
202
|
-
```sh
|
|
203
|
-
rubydb --config /etc/rubydb/production.yml --env production status --json
|
|
204
|
-
rubydb --config /etc/rubydb/production.yml --env production doctor --json
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### 3. Put one RubyDB URL in the application environment
|
|
208
|
-
|
|
209
|
-
RubyDB supports its own URL format. `rubydbs` enables TLS:
|
|
210
|
-
|
|
211
|
-
```text
|
|
212
|
-
RUBYDB_URL=rubydbs://app_user:URL_ENCODED_PASSWORD@db.internal.example:7432/my_app?verify_peer=true&ca_file=%2Fetc%2Frubydb%2Fca.crt
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
Special characters in usernames and passwords must be percent-encoded. Store
|
|
216
|
-
the complete value in a secret manager. Do not print it during deploys.
|
|
217
|
-
|
|
218
|
-
### 4. Configure Rails
|
|
219
|
-
|
|
220
|
-
```yaml
|
|
221
|
-
production:
|
|
222
|
-
adapter: rubydb
|
|
223
|
-
embedded: false
|
|
224
|
-
url: <%= ENV.fetch("RUBYDB_URL") %>
|
|
225
|
-
pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
Run the migration once from a controlled release job:
|
|
229
|
-
|
|
230
|
-
```sh
|
|
231
|
-
RAILS_ENV=production bundle exec rails db:migrate
|
|
232
|
-
RAILS_ENV=production bundle exec rails runner 'puts User.count'
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
Do not run migrations simultaneously from every web process. Confirm that the
|
|
236
|
-
Rails pool fits below the RubyDB server connection limit with room for workers,
|
|
237
|
-
monitoring, and administration.
|
|
238
|
-
|
|
239
|
-
### 5. Configure regular Ruby
|
|
240
|
-
|
|
241
|
-
```ruby
|
|
242
|
-
require "rubydb"
|
|
243
|
-
|
|
244
|
-
client = RubyDB::Client::Client.new(url: ENV.fetch("RUBYDB_URL"))
|
|
245
|
-
begin
|
|
246
|
-
result = client.query("SELECT 1")
|
|
247
|
-
puts result.to_hash
|
|
248
|
-
ensure
|
|
249
|
-
client.disconnect
|
|
250
|
-
end
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
Use idempotency keys for retried writes. A timeout or broken connection does
|
|
254
|
-
not prove that a write was rolled back; check the operation outcome before
|
|
255
|
-
retrying a non-idempotent request.
|
|
256
|
-
|
|
257
|
-
### 6. Perform a production smoke test
|
|
258
|
-
|
|
259
|
-
Before routing users:
|
|
260
|
-
|
|
261
|
-
```sh
|
|
262
|
-
RAILS_ENV=production bundle exec rails db:migrate:status
|
|
263
|
-
RAILS_ENV=production bundle exec rails runner 'puts User.limit(1).to_a.inspect'
|
|
264
|
-
rubydb --config /etc/rubydb/production.yml --env production doctor --json
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
Then test one authenticated read, one create/update/delete transaction, one
|
|
268
|
-
background job, one backup, and one restore into a separate directory. Confirm
|
|
269
|
-
logs, metrics, disk alerts, WAL/checkpoint state, and rollback ownership.
|
|
270
|
-
|
|
271
|
-
## Render-style cloud deployment
|
|
272
|
-
|
|
273
|
-
On a platform such as Render, use a private service for the RubyDB server and a
|
|
274
|
-
web service for Rails. Attach a persistent disk to the RubyDB service and set
|
|
275
|
-
`RUBYDB_URL` on the Rails service. Keep both services in the same region and
|
|
276
|
-
use the private hostname. A platform’s default filesystem is often ephemeral;
|
|
277
|
-
verify the provider’s storage behavior before using it for database files.
|
|
278
|
-
|
|
279
|
-
A single persistent disk normally means one RubyDB primary instance. Do not
|
|
280
|
-
assume that increasing the web-service instance count creates database
|
|
281
|
-
high availability. Maintain external backups and validate failover separately.
|
|
282
|
-
|
|
283
|
-
## Final beginner checklist
|
|
284
|
-
|
|
285
|
-
Before calling the app production-ready, confirm:
|
|
286
|
-
|
|
287
|
-
* the production database choice is written down;
|
|
288
|
-
* all application SQL and migrations pass against that database;
|
|
289
|
-
* credentials are environment/secret-manager values, not source files;
|
|
290
|
-
* RubyDB uses server mode when more than one process connects;
|
|
291
|
-
* TLS, authentication, private networking, and least privilege are enabled;
|
|
292
|
-
* a verified backup can be restored on another directory or host;
|
|
293
|
-
* monitoring and alerts are visible to an on-call owner;
|
|
294
|
-
* connection, lock, request, and shutdown timeouts are bounded; and
|
|
295
|
-
* rollback, data migration, and incident procedures have been rehearsed.
|
|
296
|
-
|
|
297
|
-
For deeper details, continue with [Rails compatibility](../rails/compatibility-guide.md),
|
|
298
|
-
[production operations](../operations/production-guide.md),
|
|
299
|
-
[troubleshooting](../troubleshooting.md), and [debugging](../debugging.md).
|
|
300
|
-
|
|
1
|
+
# From local development to production
|
|
2
|
+
|
|
3
|
+
This guide is for a beginner starting with a Ruby or Rails application. It
|
|
4
|
+
shows two valid deployment choices:
|
|
5
|
+
|
|
6
|
+
1. develop with RubyDB locally and deploy with PostgreSQL; or
|
|
7
|
+
2. develop with RubyDB locally and keep RubyDB in production.
|
|
8
|
+
|
|
9
|
+
The application code can be similar in both cases, but the database is not
|
|
10
|
+
interchangeable by copying files. Choose the production database before
|
|
11
|
+
launch, run the application’s migrations and query tests against it, and make
|
|
12
|
+
backups before importing important data.
|
|
13
|
+
|
|
14
|
+
## Which path should I choose?
|
|
15
|
+
|
|
16
|
+
| Goal | Local database | Production database | Recommended when |
|
|
17
|
+
| --- | --- | --- | --- |
|
|
18
|
+
| Learn/build quickly | RubyDB embedded | PostgreSQL | You want the broadest hosting and Rails ecosystem |
|
|
19
|
+
| Keep one Ruby-native database | RubyDB embedded | RubyDB server | Your SQL/workload fits RubyDB and you can operate the server |
|
|
20
|
+
| Prototype only | RubyDB embedded | RubyDB embedded | One process owns the path and data is non-critical |
|
|
21
|
+
|
|
22
|
+
For a public or business-critical application, PostgreSQL is the safer default
|
|
23
|
+
until RubyDB has been validated against your complete workload, backup/restore
|
|
24
|
+
process, concurrency, and failover requirements. RubyDB is not a complete
|
|
25
|
+
PostgreSQL or SQLite replacement.
|
|
26
|
+
|
|
27
|
+
## Part 1: local Rails development with RubyDB
|
|
28
|
+
|
|
29
|
+
### 1. Add the gems
|
|
30
|
+
|
|
31
|
+
In the Rails application `Gemfile`:
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
gem "rubydb"
|
|
35
|
+
gem "rubydb-activerecord"
|
|
36
|
+
gem "pg" # Keep this if PostgreSQL is a possible production target.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Run:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
bundle install
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Configure development and test
|
|
46
|
+
|
|
47
|
+
Use an embedded path for local development. Only the Rails process should own
|
|
48
|
+
each path:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
default: &default
|
|
52
|
+
adapter: rubydb
|
|
53
|
+
embedded: true
|
|
54
|
+
database: <%= Rails.root.join("tmp/rubydb_development.rdb") %>
|
|
55
|
+
pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
|
|
56
|
+
|
|
57
|
+
development:
|
|
58
|
+
<<: *default
|
|
59
|
+
|
|
60
|
+
test:
|
|
61
|
+
<<: *default
|
|
62
|
+
database: <%= Rails.root.join("tmp/rubydb_test.rdb") %>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Use separate development and test paths. Do not put the database under a
|
|
66
|
+
source-controlled directory. Do not let a web server, job worker, and console
|
|
67
|
+
open the same embedded path at the same time.
|
|
68
|
+
|
|
69
|
+
### 3. Create the schema and run the app
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
bin/rails db:create
|
|
73
|
+
bin/rails db:migrate
|
|
74
|
+
bin/rails db:seed # only if your seed data is safe to recreate
|
|
75
|
+
bin/rails test
|
|
76
|
+
bin/rails server
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Exercise real application flows: sign-up, login, CRUD, joins, eager loading,
|
|
80
|
+
background jobs, file metadata, transactions, and error handling. Do not test
|
|
81
|
+
only that the server boots.
|
|
82
|
+
|
|
83
|
+
### 4. Use RubyDB in a regular Ruby app
|
|
84
|
+
|
|
85
|
+
Local single-process code can use the embedded engine:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
require "rubydb"
|
|
89
|
+
|
|
90
|
+
engine = RubyDB::Storage::Engine.new("tmp/app.rdb")
|
|
91
|
+
begin
|
|
92
|
+
engine.execute("CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY, name TEXT)")
|
|
93
|
+
engine.execute("INSERT INTO events (name) VALUES (?)", ["boot"])
|
|
94
|
+
p engine.execute("SELECT * FROM events")
|
|
95
|
+
ensure
|
|
96
|
+
engine.close
|
|
97
|
+
end
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
For multiple processes, use the client/server connection described below.
|
|
101
|
+
|
|
102
|
+
## Part 2A: deploy the same app on PostgreSQL
|
|
103
|
+
|
|
104
|
+
This path keeps RubyDB for local development and uses PostgreSQL in production.
|
|
105
|
+
It is a database migration, not a file copy.
|
|
106
|
+
|
|
107
|
+
### 1. Configure the production Rails block
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
production:
|
|
111
|
+
adapter: postgresql
|
|
112
|
+
url: <%= ENV.fetch("DATABASE_URL") %>
|
|
113
|
+
pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The hosting provider supplies a PostgreSQL URL such as:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
postgresql://app_user:password@postgres.example.com:5432/my_app
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Keep `DATABASE_URL` in the provider’s secret settings. Never commit it.
|
|
123
|
+
|
|
124
|
+
### 2. Review the schema and SQL
|
|
125
|
+
|
|
126
|
+
Before switching, review RubyDB-specific behavior:
|
|
127
|
+
|
|
128
|
+
* integer primary-key/autoincrement behavior;
|
|
129
|
+
* `BOOLEAN`, `JSON`, `UUID`, dates, timestamps, and decimals;
|
|
130
|
+
* indexes, foreign keys, check constraints, and defaults;
|
|
131
|
+
* `NULL`, ordering, grouping, joins, upserts, and functions;
|
|
132
|
+
* migrations that alter populated tables; and
|
|
133
|
+
* raw SQL, extensions, pragmas, and database-specific functions.
|
|
134
|
+
|
|
135
|
+
Run `db:schema:dump` and inspect the generated schema. Do not assume every
|
|
136
|
+
RubyDB schema statement is valid PostgreSQL syntax. Fix migrations or use
|
|
137
|
+
adapter-specific migrations deliberately and document the difference.
|
|
138
|
+
|
|
139
|
+
### 3. Transfer data safely
|
|
140
|
+
|
|
141
|
+
RubyDB `.rdb` files cannot be opened by PostgreSQL. A safe small-dataset flow is:
|
|
142
|
+
|
|
143
|
+
1. stop writes to the RubyDB application;
|
|
144
|
+
2. create a verified RubyDB backup;
|
|
145
|
+
3. create the PostgreSQL database and run reviewed migrations;
|
|
146
|
+
4. export each table in a deterministic order, including parent tables first;
|
|
147
|
+
5. transform types and IDs explicitly;
|
|
148
|
+
6. import into PostgreSQL using bound/escaped data or PostgreSQL `COPY`;
|
|
149
|
+
7. compare row counts, checksums, foreign keys, indexes, and business totals;
|
|
150
|
+
8. run the application test and smoke suite against PostgreSQL; and
|
|
151
|
+
9. switch traffic only after the verification report is approved.
|
|
152
|
+
|
|
153
|
+
For large or live data, use a purpose-built migration process with checkpoints,
|
|
154
|
+
retries, idempotency, and a cutover plan. Do not write a one-off script that
|
|
155
|
+
silently skips a row or converts an unknown type to text.
|
|
156
|
+
|
|
157
|
+
### 4. Test production configuration before cutover
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
RAILS_ENV=production DATABASE_URL='postgresql://...' bin/rails db:migrate
|
|
161
|
+
RAILS_ENV=production DATABASE_URL='postgresql://...' bin/rails db:seed
|
|
162
|
+
RAILS_ENV=production DATABASE_URL='postgresql://...' bin/rails test
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Run this against a restored staging database, not the only production copy.
|
|
166
|
+
Keep the RubyDB backup until PostgreSQL row counts and application behavior
|
|
167
|
+
have been accepted.
|
|
168
|
+
|
|
169
|
+
## Part 2B: deploy RubyDB in production
|
|
170
|
+
|
|
171
|
+
This path runs one managed RubyDB server and connects Rails/Ruby processes to it
|
|
172
|
+
over the RubyDB protocol. The application never opens the server’s data file.
|
|
173
|
+
|
|
174
|
+
### 1. Provision a database host
|
|
175
|
+
|
|
176
|
+
Install a pinned RubyDB release, create a dedicated service account, and attach
|
|
177
|
+
persistent storage. The data directory must survive process restarts and
|
|
178
|
+
deploys. Keep backups on a separate system or failure domain.
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
gem install rubydb -v 0.1.0
|
|
182
|
+
install -d -o rubydb -g rubydb -m 0700 /var/lib/rubydb/data
|
|
183
|
+
install -d -o rubydb -g rubydb -m 0750 /var/log/rubydb
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Use the complete setup in the [production operations guide](../operations/production-guide.md)
|
|
187
|
+
for service supervision, TLS, authentication, resource limits, backups, and
|
|
188
|
+
monitoring.
|
|
189
|
+
|
|
190
|
+
### 2. Start the RubyDB server
|
|
191
|
+
|
|
192
|
+
Use a reviewed production configuration with WAL, authentication, TLS, and
|
|
193
|
+
bounded resources:
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
rubydb --config /etc/rubydb/production.yml --env production start
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Keep port `7432` on a private network. Verify the server before connecting the
|
|
200
|
+
application:
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
rubydb --config /etc/rubydb/production.yml --env production status --json
|
|
204
|
+
rubydb --config /etc/rubydb/production.yml --env production doctor --json
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 3. Put one RubyDB URL in the application environment
|
|
208
|
+
|
|
209
|
+
RubyDB supports its own URL format. `rubydbs` enables TLS:
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
RUBYDB_URL=rubydbs://app_user:URL_ENCODED_PASSWORD@db.internal.example:7432/my_app?verify_peer=true&ca_file=%2Fetc%2Frubydb%2Fca.crt
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Special characters in usernames and passwords must be percent-encoded. Store
|
|
216
|
+
the complete value in a secret manager. Do not print it during deploys.
|
|
217
|
+
|
|
218
|
+
### 4. Configure Rails
|
|
219
|
+
|
|
220
|
+
```yaml
|
|
221
|
+
production:
|
|
222
|
+
adapter: rubydb
|
|
223
|
+
embedded: false
|
|
224
|
+
url: <%= ENV.fetch("RUBYDB_URL") %>
|
|
225
|
+
pool: <%= ENV.fetch("RAILS_MAX_THREADS", "5") %>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Run the migration once from a controlled release job:
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
RAILS_ENV=production bundle exec rails db:migrate
|
|
232
|
+
RAILS_ENV=production bundle exec rails runner 'puts User.count'
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Do not run migrations simultaneously from every web process. Confirm that the
|
|
236
|
+
Rails pool fits below the RubyDB server connection limit with room for workers,
|
|
237
|
+
monitoring, and administration.
|
|
238
|
+
|
|
239
|
+
### 5. Configure regular Ruby
|
|
240
|
+
|
|
241
|
+
```ruby
|
|
242
|
+
require "rubydb"
|
|
243
|
+
|
|
244
|
+
client = RubyDB::Client::Client.new(url: ENV.fetch("RUBYDB_URL"))
|
|
245
|
+
begin
|
|
246
|
+
result = client.query("SELECT 1")
|
|
247
|
+
puts result.to_hash
|
|
248
|
+
ensure
|
|
249
|
+
client.disconnect
|
|
250
|
+
end
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Use idempotency keys for retried writes. A timeout or broken connection does
|
|
254
|
+
not prove that a write was rolled back; check the operation outcome before
|
|
255
|
+
retrying a non-idempotent request.
|
|
256
|
+
|
|
257
|
+
### 6. Perform a production smoke test
|
|
258
|
+
|
|
259
|
+
Before routing users:
|
|
260
|
+
|
|
261
|
+
```sh
|
|
262
|
+
RAILS_ENV=production bundle exec rails db:migrate:status
|
|
263
|
+
RAILS_ENV=production bundle exec rails runner 'puts User.limit(1).to_a.inspect'
|
|
264
|
+
rubydb --config /etc/rubydb/production.yml --env production doctor --json
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Then test one authenticated read, one create/update/delete transaction, one
|
|
268
|
+
background job, one backup, and one restore into a separate directory. Confirm
|
|
269
|
+
logs, metrics, disk alerts, WAL/checkpoint state, and rollback ownership.
|
|
270
|
+
|
|
271
|
+
## Render-style cloud deployment
|
|
272
|
+
|
|
273
|
+
On a platform such as Render, use a private service for the RubyDB server and a
|
|
274
|
+
web service for Rails. Attach a persistent disk to the RubyDB service and set
|
|
275
|
+
`RUBYDB_URL` on the Rails service. Keep both services in the same region and
|
|
276
|
+
use the private hostname. A platform’s default filesystem is often ephemeral;
|
|
277
|
+
verify the provider’s storage behavior before using it for database files.
|
|
278
|
+
|
|
279
|
+
A single persistent disk normally means one RubyDB primary instance. Do not
|
|
280
|
+
assume that increasing the web-service instance count creates database
|
|
281
|
+
high availability. Maintain external backups and validate failover separately.
|
|
282
|
+
|
|
283
|
+
## Final beginner checklist
|
|
284
|
+
|
|
285
|
+
Before calling the app production-ready, confirm:
|
|
286
|
+
|
|
287
|
+
* the production database choice is written down;
|
|
288
|
+
* all application SQL and migrations pass against that database;
|
|
289
|
+
* credentials are environment/secret-manager values, not source files;
|
|
290
|
+
* RubyDB uses server mode when more than one process connects;
|
|
291
|
+
* TLS, authentication, private networking, and least privilege are enabled;
|
|
292
|
+
* a verified backup can be restored on another directory or host;
|
|
293
|
+
* monitoring and alerts are visible to an on-call owner;
|
|
294
|
+
* connection, lock, request, and shutdown timeouts are bounded; and
|
|
295
|
+
* rollback, data migration, and incident procedures have been rehearsed.
|
|
296
|
+
|
|
297
|
+
For deeper details, continue with [Rails compatibility](../rails/compatibility-guide.md),
|
|
298
|
+
[production operations](../operations/production-guide.md),
|
|
299
|
+
[troubleshooting](../troubleshooting.md), and [debugging](../debugging.md).
|
|
300
|
+
|