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