rubydb 0.1.0
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 +7 -0
- data/.gitattributes +20 -0
- data/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- data/.github/ISSUE_TEMPLATE/feature.yml +0 -0
- data/.github/ISSUE_TEMPLATE/performance.yml +0 -0
- data/.github/ISSUE_TEMPLATE/security.yml +0 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- data/.github/dependabot.yml +0 -0
- data/.github/workflows/benchmark.yml +26 -0
- data/.github/workflows/compatibility.yml +63 -0
- data/.github/workflows/fuzz.yml +33 -0
- data/.github/workflows/lint.yml +21 -0
- data/.github/workflows/operations.yml +24 -0
- data/.github/workflows/production-validation.yml +111 -0
- data/.github/workflows/release.yml +77 -0
- data/.github/workflows/security.yml +37 -0
- data/.github/workflows/test.yml +26 -0
- data/.github/workflows/workload.yml +58 -0
- data/.gitignore +43 -0
- data/.rspec +4 -0
- data/.rubocop.yml +44 -0
- data/.ruby-version +1 -0
- data/.standard.yml +14 -0
- data/ARCHITECTURE.md +21 -0
- data/CHANGELOG.md +31 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/CONTRIBUTING.md +29 -0
- data/GOVERNANCE.md +16 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +71 -0
- data/LICENSE +60 -0
- data/README.md +162 -0
- data/ROADMAP.md +27 -0
- data/Rakefile +71 -0
- data/SECURITY.md +54 -0
- data/SUPPORT.md +14 -0
- data/adapters/activerecord/Gemfile +11 -0
- data/adapters/activerecord/README.md +9 -0
- data/adapters/activerecord/lib/active_record/connection_adapters/rubydb_adapter.rb +887 -0
- data/adapters/activerecord/rubydb-activerecord.gemspec +27 -0
- data/adapters/activerecord/spec/rubydb_adapter_integration_spec.rb +151 -0
- data/adapters/ruby/README.md +18 -0
- data/adapters/sequel/README.md +11 -0
- data/bin/rubydb +19 -0
- data/bin/rubydb-server +126 -0
- data/config/development.yml +0 -0
- data/config/monitoring/prometheus-alerts.yml +39 -0
- data/config/production.yml +36 -0
- data/config/test.yml +0 -0
- data/docs/README.md +71 -0
- data/docs/architecture/concurrency.md +14 -0
- data/docs/architecture/current-state.md +125 -0
- data/docs/architecture/execution-engine.md +25 -0
- data/docs/architecture/indexes.md +19 -0
- data/docs/architecture/mvcc.md +19 -0
- data/docs/architecture/overview.md +13 -0
- data/docs/architecture/pages.md +11 -0
- data/docs/architecture/production-roadmap.md +82 -0
- data/docs/architecture/query-planner.md +20 -0
- data/docs/architecture/recovery.md +18 -0
- data/docs/architecture/sql-engine.md +12 -0
- data/docs/architecture/storage-engine.md +14 -0
- data/docs/architecture/transactions.md +10 -0
- data/docs/architecture/wal.md +28 -0
- data/docs/cli-cheatsheet.md +98 -0
- data/docs/cli.md +275 -0
- data/docs/contributing/architecture.md +9 -0
- data/docs/contributing/benchmarking.md +14 -0
- data/docs/contributing/development.md +16 -0
- data/docs/contributing/release-process.md +49 -0
- data/docs/contributing/testing.md +16 -0
- data/docs/debugging.md +229 -0
- data/docs/developer/branching.md +10 -0
- data/docs/developer/database-diff.md +10 -0
- data/docs/developer/local-development.md +17 -0
- data/docs/developer/snapshots.md +9 -0
- data/docs/developer/temporal-data.md +10 -0
- data/docs/developer-guide.md +297 -0
- data/docs/getting-started/first-database.md +16 -0
- data/docs/getting-started/first-query.md +13 -0
- data/docs/getting-started/installation.md +19 -0
- data/docs/getting-started/local-to-production.md +300 -0
- data/docs/getting-started/quickstart.md +17 -0
- data/docs/getting-started/rails.md +16 -0
- data/docs/hardening_backlog.md +93 -0
- data/docs/lessons-learned.md +112 -0
- data/docs/operations/backups.md +33 -0
- data/docs/operations/disaster-recovery.md +31 -0
- data/docs/operations/failover.md +30 -0
- data/docs/operations/monitoring.md +25 -0
- data/docs/operations/production-guide.md +295 -0
- data/docs/operations/production-runbook.md +45 -0
- data/docs/operations/replication.md +33 -0
- data/docs/operations/restore.md +6 -0
- data/docs/operations/runbook.md +34 -0
- data/docs/operations/upgrades.md +14 -0
- data/docs/operations/workload-testing.md +17 -0
- data/docs/production-readiness.md +118 -0
- data/docs/production_validation.md +150 -0
- data/docs/rails/active-record.md +11 -0
- data/docs/rails/compatibility-guide.md +90 -0
- data/docs/rails/database-yml.md +92 -0
- data/docs/rails/installation.md +17 -0
- data/docs/rails/migrations.md +17 -0
- data/docs/rails/production.md +82 -0
- data/docs/rails/troubleshooting.md +18 -0
- data/docs/release.md +59 -0
- data/docs/server/architecture.md +10 -0
- data/docs/server/authentication.md +10 -0
- data/docs/server/configuration.md +16 -0
- data/docs/server/connection-pooling.md +10 -0
- data/docs/server/deployment.md +10 -0
- data/docs/server/protocol.md +12 -0
- data/docs/sql/compatibility-guide.md +82 -0
- data/docs/sql/compatibility.md +39 -0
- data/docs/sql/data-types.md +10 -0
- data/docs/sql/functions.md +9 -0
- data/docs/sql/joins.md +9 -0
- data/docs/sql/operators.md +9 -0
- data/docs/sql/sqlite-compatibility.md +21 -0
- data/docs/sql/syntax.md +10 -0
- data/docs/sql/transactions.md +10 -0
- data/docs/troubleshooting.md +244 -0
- data/exe/rubydb +23 -0
- data/lib/rubydb/backup/archive.rb +334 -0
- data/lib/rubydb/backup/backup.rb +401 -0
- data/lib/rubydb/backup/incremental.rb +353 -0
- data/lib/rubydb/backup/restore.rb +290 -0
- data/lib/rubydb/backup/snapshot.rb +267 -0
- data/lib/rubydb/backup/verification.rb +279 -0
- data/lib/rubydb/branching/branch.rb +181 -0
- data/lib/rubydb/branching/branch_manager.rb +311 -0
- data/lib/rubydb/branching/branch_metadata.rb +140 -0
- data/lib/rubydb/branching/checkout.rb +166 -0
- data/lib/rubydb/branching/copy_on_write.rb +272 -0
- data/lib/rubydb/branching/diff.rb +138 -0
- data/lib/rubydb/branching/merge.rb +285 -0
- data/lib/rubydb/build_info.rb +15 -0
- data/lib/rubydb/catalog/catalog.rb +391 -0
- data/lib/rubydb/catalog/column.rb +112 -0
- data/lib/rubydb/catalog/constraint.rb +180 -0
- data/lib/rubydb/catalog/database.rb +184 -0
- data/lib/rubydb/catalog/index.rb +97 -0
- data/lib/rubydb/catalog/schema.rb +103 -0
- data/lib/rubydb/catalog/sequence.rb +90 -0
- data/lib/rubydb/catalog/system_catalog.rb +698 -0
- data/lib/rubydb/catalog/table.rb +178 -0
- data/lib/rubydb/catalog/trigger.rb +102 -0
- data/lib/rubydb/catalog/view.rb +66 -0
- data/lib/rubydb/cli/application.rb +163 -0
- data/lib/rubydb/cli/commands/backup.rb +81 -0
- data/lib/rubydb/cli/commands/branch.rb +72 -0
- data/lib/rubydb/cli/commands/checkout.rb +54 -0
- data/lib/rubydb/cli/commands/create.rb +58 -0
- data/lib/rubydb/cli/commands/diff.rb +77 -0
- data/lib/rubydb/cli/commands/doctor.rb +74 -0
- data/lib/rubydb/cli/commands/drop.rb +57 -0
- data/lib/rubydb/cli/commands/init.rb +102 -0
- data/lib/rubydb/cli/commands/inspect.rb +95 -0
- data/lib/rubydb/cli/commands/merge.rb +63 -0
- data/lib/rubydb/cli/commands/migrate.rb +62 -0
- data/lib/rubydb/cli/commands/restart.rb +39 -0
- data/lib/rubydb/cli/commands/restore.rb +121 -0
- data/lib/rubydb/cli/commands/shell.rb +365 -0
- data/lib/rubydb/cli/commands/snapshot.rb +79 -0
- data/lib/rubydb/cli/commands/start.rb +82 -0
- data/lib/rubydb/cli/commands/status.rb +92 -0
- data/lib/rubydb/cli/commands/stop.rb +47 -0
- data/lib/rubydb/cli/commands/vacuum.rb +58 -0
- data/lib/rubydb/cli/formatter.rb +221 -0
- data/lib/rubydb/cli/output.rb +168 -0
- data/lib/rubydb/client/client.rb +304 -0
- data/lib/rubydb/client/connection.rb +415 -0
- data/lib/rubydb/client/connection_pool.rb +168 -0
- data/lib/rubydb/client/connection_url.rb +96 -0
- data/lib/rubydb/client/prepared_statement.rb +60 -0
- data/lib/rubydb/client/result.rb +123 -0
- data/lib/rubydb/client/statement.rb +52 -0
- data/lib/rubydb/client/transaction.rb +130 -0
- data/lib/rubydb/concurrency/concurrency.rb +19 -0
- data/lib/rubydb/concurrency/deadlock_detector.rb +150 -0
- data/lib/rubydb/concurrency/latch.rb +101 -0
- data/lib/rubydb/concurrency/lock_graph.rb +165 -0
- data/lib/rubydb/concurrency/mutex.rb +183 -0
- data/lib/rubydb/concurrency/rw_lock.rb +180 -0
- data/lib/rubydb/concurrency/scheduler.rb +250 -0
- data/lib/rubydb/concurrency/worker_pool.rb +143 -0
- data/lib/rubydb/configuration/config.rb +170 -0
- data/lib/rubydb/configuration/defaults.rb +179 -0
- data/lib/rubydb/configuration/environment.rb +152 -0
- data/lib/rubydb/configuration/parser.rb +185 -0
- data/lib/rubydb/configuration/validation.rb +221 -0
- data/lib/rubydb/constants.rb +74 -0
- data/lib/rubydb/constraints/check.rb +181 -0
- data/lib/rubydb/constraints/constraint.rb +101 -0
- data/lib/rubydb/constraints/foreign_key.rb +130 -0
- data/lib/rubydb/constraints/not_null.rb +64 -0
- data/lib/rubydb/constraints/primary_key.rb +99 -0
- data/lib/rubydb/constraints/unique.rb +108 -0
- data/lib/rubydb/constraints/validator.rb +350 -0
- data/lib/rubydb/errors/authentication_error.rb +10 -0
- data/lib/rubydb/errors/authorization_error.rb +23 -0
- data/lib/rubydb/errors/client_error.rb +10 -0
- data/lib/rubydb/errors/configuration_error.rb +10 -0
- data/lib/rubydb/errors/connection_error.rb +10 -0
- data/lib/rubydb/errors/constraint_error.rb +23 -0
- data/lib/rubydb/errors/corruption_error.rb +10 -0
- data/lib/rubydb/errors/database_error.rb +10 -0
- data/lib/rubydb/errors/error.rb +20 -0
- data/lib/rubydb/errors/execution_error.rb +10 -0
- data/lib/rubydb/errors/parser_error.rb +10 -0
- data/lib/rubydb/errors/recovery_error.rb +10 -0
- data/lib/rubydb/errors/replication_error.rb +10 -0
- data/lib/rubydb/errors/server_error.rb +6 -0
- data/lib/rubydb/errors/storage_error.rb +10 -0
- data/lib/rubydb/errors/transaction_error.rb +10 -0
- data/lib/rubydb/execution/aggregate_executor.rb +138 -0
- data/lib/rubydb/execution/delete_executor.rb +112 -0
- data/lib/rubydb/execution/distinct_executor.rb +135 -0
- data/lib/rubydb/execution/executor.rb +1192 -0
- data/lib/rubydb/execution/expression.rb +193 -0
- data/lib/rubydb/execution/index_scan.rb +142 -0
- data/lib/rubydb/execution/insert_executor.rb +217 -0
- data/lib/rubydb/execution/join_executor.rb +249 -0
- data/lib/rubydb/execution/limit_executor.rb +85 -0
- data/lib/rubydb/execution/optimizer.rb +215 -0
- data/lib/rubydb/execution/plan.rb +361 -0
- data/lib/rubydb/execution/planner.rb +546 -0
- data/lib/rubydb/execution/predicate.rb +235 -0
- data/lib/rubydb/execution/scan.rb +49 -0
- data/lib/rubydb/execution/sequential_scan.rb +63 -0
- data/lib/rubydb/execution/sort_executor.rb +185 -0
- data/lib/rubydb/execution/update_executor.rb +162 -0
- data/lib/rubydb/functions/aggregate.rb +70 -0
- data/lib/rubydb/functions/date_functions.rb +278 -0
- data/lib/rubydb/functions/function.rb +85 -0
- data/lib/rubydb/functions/json_functions.rb +215 -0
- data/lib/rubydb/functions/numeric_functions.rb +346 -0
- data/lib/rubydb/functions/scalar.rb +52 -0
- data/lib/rubydb/functions/string_functions.rb +383 -0
- data/lib/rubydb/functions/system_functions.rb +246 -0
- data/lib/rubydb/history/as_of.rb +238 -0
- data/lib/rubydb/history/change.rb +105 -0
- data/lib/rubydb/history/history.rb +131 -0
- data/lib/rubydb/history/history_manager.rb +229 -0
- data/lib/rubydb/history/temporal_query.rb +202 -0
- data/lib/rubydb/history/timeline.rb +144 -0
- data/lib/rubydb/indexes/btree.rb +186 -0
- data/lib/rubydb/indexes/btree_cursor.rb +258 -0
- data/lib/rubydb/indexes/btree_node.rb +385 -0
- data/lib/rubydb/indexes/hash_index.rb +150 -0
- data/lib/rubydb/indexes/index.rb +71 -0
- data/lib/rubydb/indexes/index_manager.rb +406 -0
- data/lib/rubydb/indexes/index_scan.rb +470 -0
- data/lib/rubydb/migrations/migration.rb +254 -0
- data/lib/rubydb/migrations/migration_lock.rb +146 -0
- data/lib/rubydb/migrations/migration_manager.rb +176 -0
- data/lib/rubydb/migrations/migration_version.rb +71 -0
- data/lib/rubydb/migrations/schema_diff.rb +211 -0
- data/lib/rubydb/migrations/schema_version.rb +64 -0
- data/lib/rubydb/monitoring/events.rb +160 -0
- data/lib/rubydb/monitoring/health.rb +222 -0
- data/lib/rubydb/monitoring/logger.rb +193 -0
- data/lib/rubydb/monitoring/metrics.rb +359 -0
- data/lib/rubydb/monitoring/performance.rb +176 -0
- data/lib/rubydb/monitoring/statistics.rb +170 -0
- data/lib/rubydb/mvcc/garbage_collector.rb +199 -0
- data/lib/rubydb/mvcc/mvcc.rb +16 -0
- data/lib/rubydb/mvcc/snapshot.rb +147 -0
- data/lib/rubydb/mvcc/vacuum.rb +180 -0
- data/lib/rubydb/mvcc/version.rb +106 -0
- data/lib/rubydb/mvcc/version_store.rb +398 -0
- data/lib/rubydb/mvcc/visibility.rb +109 -0
- data/lib/rubydb/protocol/capabilities.rb +125 -0
- data/lib/rubydb/protocol/decoder.rb +145 -0
- data/lib/rubydb/protocol/encoder.rb +136 -0
- data/lib/rubydb/protocol/handshake.rb +305 -0
- data/lib/rubydb/protocol/message.rb +121 -0
- data/lib/rubydb/protocol/protocol.rb +277 -0
- data/lib/rubydb/protocol/version.rb +54 -0
- data/lib/rubydb/rails/adapter.rb +239 -0
- data/lib/rubydb/rails/connection.rb +314 -0
- data/lib/rubydb/rails/database_statements.rb +122 -0
- data/lib/rubydb/rails/migration.rb +131 -0
- data/lib/rubydb/rails/quoting.rb +109 -0
- data/lib/rubydb/rails/result.rb +120 -0
- data/lib/rubydb/rails/schema_statements.rb +339 -0
- data/lib/rubydb/rails/transaction.rb +105 -0
- data/lib/rubydb/rails/type.rb +126 -0
- data/lib/rubydb/recovery/checkpoint.rb +257 -0
- data/lib/rubydb/recovery/consistency.rb +467 -0
- data/lib/rubydb/recovery/corruption_detector.rb +5 -0
- data/lib/rubydb/recovery/crash_recovery.rb +387 -0
- data/lib/rubydb/recovery/recovery_manager.rb +206 -0
- data/lib/rubydb/recovery/redo.rb +237 -0
- data/lib/rubydb/recovery/undo.rb +206 -0
- data/lib/rubydb/replication/failover.rb +5 -0
- data/lib/rubydb/replication/fencing.rb +63 -0
- data/lib/rubydb/replication/primary.rb +450 -0
- data/lib/rubydb/replication/replica.rb +384 -0
- data/lib/rubydb/replication/replication_log.rb +200 -0
- data/lib/rubydb/replication/replication_manager.rb +308 -0
- data/lib/rubydb/replication/replication_slot.rb +295 -0
- data/lib/rubydb/replication/replication_stream.rb +201 -0
- data/lib/rubydb/rubydb.rb +560 -0
- data/lib/rubydb/security/access_control.rb +254 -0
- data/lib/rubydb/security/audit_log.rb +213 -0
- data/lib/rubydb/security/authentication.rb +302 -0
- data/lib/rubydb/security/authorization.rb +282 -0
- data/lib/rubydb/security/credentials.rb +196 -0
- data/lib/rubydb/security/password.rb +215 -0
- data/lib/rubydb/security/permissions.rb +74 -0
- data/lib/rubydb/security/role.rb +101 -0
- data/lib/rubydb/security/user.rb +86 -0
- data/lib/rubydb/server/connection.rb +366 -0
- data/lib/rubydb/server/connection_pool.rb +193 -0
- data/lib/rubydb/server/lifecycle.rb +228 -0
- data/lib/rubydb/server/listener.rb +136 -0
- data/lib/rubydb/server/request_handler.rb +276 -0
- data/lib/rubydb/server/server.rb +364 -0
- data/lib/rubydb/server/session.rb +369 -0
- data/lib/rubydb/server/worker.rb +210 -0
- data/lib/rubydb/server/worker_pool.rb +168 -0
- data/lib/rubydb/sql/ast/alter_table.rb +169 -0
- data/lib/rubydb/sql/ast/begin_transaction.rb +47 -0
- data/lib/rubydb/sql/ast/commit.rb +37 -0
- data/lib/rubydb/sql/ast/constraint.rb +83 -0
- data/lib/rubydb/sql/ast/create_database.rb +41 -0
- data/lib/rubydb/sql/ast/create_index.rb +61 -0
- data/lib/rubydb/sql/ast/create_schema.rb +52 -0
- data/lib/rubydb/sql/ast/create_table.rb +187 -0
- data/lib/rubydb/sql/ast/delete.rb +54 -0
- data/lib/rubydb/sql/ast/drop_database.rb +41 -0
- data/lib/rubydb/sql/ast/drop_index.rb +41 -0
- data/lib/rubydb/sql/ast/drop_schema.rb +49 -0
- data/lib/rubydb/sql/ast/drop_table.rb +49 -0
- data/lib/rubydb/sql/ast/explain.rb +64 -0
- data/lib/rubydb/sql/ast/expression.rb +604 -0
- data/lib/rubydb/sql/ast/insert.rb +82 -0
- data/lib/rubydb/sql/ast/node.rb +42 -0
- data/lib/rubydb/sql/ast/rollback.rb +63 -0
- data/lib/rubydb/sql/ast/savepoint.rb +59 -0
- data/lib/rubydb/sql/ast/select.rb +88 -0
- data/lib/rubydb/sql/ast/set_operation.rb +20 -0
- data/lib/rubydb/sql/ast/trigger.rb +29 -0
- data/lib/rubydb/sql/ast/update.rb +88 -0
- data/lib/rubydb/sql/ast/vacuum.rb +19 -0
- data/lib/rubydb/sql/ast/view.rb +32 -0
- data/lib/rubydb/sql/ast/with.rb +32 -0
- data/lib/rubydb/sql/grammar.rb +86 -0
- data/lib/rubydb/sql/keywords.rb +156 -0
- data/lib/rubydb/sql/lexer.rb +214 -0
- data/lib/rubydb/sql/operators.rb +100 -0
- data/lib/rubydb/sql/parser.rb +1185 -0
- data/lib/rubydb/sql/planner/analyzer.rb +302 -0
- data/lib/rubydb/sql/planner/binder.rb +550 -0
- data/lib/rubydb/sql/planner/type_checker.rb +431 -0
- data/lib/rubydb/sql/token.rb +210 -0
- data/lib/rubydb/storage/buffer_frame.rb +44 -0
- data/lib/rubydb/storage/buffer_pool.rb +155 -0
- data/lib/rubydb/storage/database_lock.rb +74 -0
- data/lib/rubydb/storage/deserializer.rb +342 -0
- data/lib/rubydb/storage/engine.rb +2338 -0
- data/lib/rubydb/storage/file_manager.rb +187 -0
- data/lib/rubydb/storage/free_space_map.rb +81 -0
- data/lib/rubydb/storage/page.rb +94 -0
- data/lib/rubydb/storage/page_allocator.rb +855 -0
- data/lib/rubydb/storage/page_header.rb +67 -0
- data/lib/rubydb/storage/page_manager.rb +131 -0
- data/lib/rubydb/storage/record.rb +58 -0
- data/lib/rubydb/storage/row.rb +78 -0
- data/lib/rubydb/storage/serializer.rb +51 -0
- data/lib/rubydb/storage/storage_layout.rb +151 -0
- data/lib/rubydb/storage/storage_manager.rb +114 -0
- data/lib/rubydb/storage/tuple.rb +461 -0
- data/lib/rubydb/storage/visibility_map.rb +984 -0
- data/lib/rubydb/transactions/commit_manager.rb +220 -0
- data/lib/rubydb/transactions/isolation.rb +98 -0
- data/lib/rubydb/transactions/lock.rb +76 -0
- data/lib/rubydb/transactions/lock_manager.rb +362 -0
- data/lib/rubydb/transactions/savepoint.rb +143 -0
- data/lib/rubydb/transactions/transaction.rb +215 -0
- data/lib/rubydb/transactions/transaction_id.rb +84 -0
- data/lib/rubydb/transactions/transaction_log.rb +257 -0
- data/lib/rubydb/transactions/transaction_manager.rb +435 -0
- data/lib/rubydb/types/bigint.rb +36 -0
- data/lib/rubydb/types/blob.rb +37 -0
- data/lib/rubydb/types/boolean.rb +34 -0
- data/lib/rubydb/types/date.rb +39 -0
- data/lib/rubydb/types/decimal.rb +48 -0
- data/lib/rubydb/types/float.rb +34 -0
- data/lib/rubydb/types/integer.rb +36 -0
- data/lib/rubydb/types/json.rb +41 -0
- data/lib/rubydb/types/null.rb +34 -0
- data/lib/rubydb/types/smallint.rb +36 -0
- data/lib/rubydb/types/text.rb +37 -0
- data/lib/rubydb/types/time.rb +46 -0
- data/lib/rubydb/types/timestamp.rb +39 -0
- data/lib/rubydb/types/type.rb +119 -0
- data/lib/rubydb/types/uuid.rb +47 -0
- data/lib/rubydb/types/varchar.rb +37 -0
- data/lib/rubydb/version.rb +33 -0
- data/lib/rubydb/wal/archive.rb +193 -0
- data/lib/rubydb/wal/checkpoint.rb +183 -0
- data/lib/rubydb/wal/lsn.rb +94 -0
- data/lib/rubydb/wal/reader.rb +260 -0
- data/lib/rubydb/wal/record.rb +105 -0
- data/lib/rubydb/wal/segment.rb +193 -0
- data/lib/rubydb/wal/wal.rb +452 -0
- data/lib/rubydb/wal/writer.rb +236 -0
- data/lib/rubydb.rb +7 -0
- data/packaging/docker/Dockerfile +36 -0
- data/packaging/docker/docker-compose.failover.yml +43 -0
- data/packaging/docker/entrypoint.sh +15 -0
- data/packaging/homebrew/rubydb.rb +19 -0
- data/packaging/systemd/rubydb.service +22 -0
- data/rubydb.gemspec +57 -0
- data/scripts/benchmark +7 -0
- data/scripts/durability_drill +37 -0
- data/scripts/format +0 -0
- data/scripts/fuzz +63 -0
- data/scripts/lint +0 -0
- data/scripts/release +50 -0
- data/scripts/release_check +43 -0
- data/scripts/replication_failover_drill +250 -0
- data/scripts/replication_network_failover_drill +255 -0
- data/scripts/restore_drill +45 -0
- data/scripts/security +0 -0
- data/scripts/setup +0 -0
- data/scripts/test +0 -0
- data/scripts/test-chaos +0 -0
- data/scripts/test-crash +0 -0
- data/scripts/test-integration +0 -0
- data/scripts/test-unit +0 -0
- data/visibility_map.json +1 -0
- metadata +538 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# SQL compatibility guide
|
|
2
|
+
|
|
3
|
+
This page is a developer reference for evaluating SQL support. The normative
|
|
4
|
+
statement list is [SQL compatibility](compatibility.md); the SQLite-style
|
|
5
|
+
application profile is [here](sqlite-compatibility.md). RubyDB does not claim
|
|
6
|
+
complete PostgreSQL, MySQL, or SQLite dialect compatibility.
|
|
7
|
+
|
|
8
|
+
## Compatibility has four layers
|
|
9
|
+
|
|
10
|
+
An SQL feature is production-ready only when all four layers agree:
|
|
11
|
+
|
|
12
|
+
1. syntax is parsed and rejected with useful errors;
|
|
13
|
+
2. binding and type rules are defined, including `NULL`;
|
|
14
|
+
3. planner/executor results and transaction semantics are correct; and
|
|
15
|
+
4. Ruby, client/server, and ActiveRecord paths behave consistently.
|
|
16
|
+
|
|
17
|
+
A parser accepting a statement is not sufficient. Test duplicate rows,
|
|
18
|
+
ordering, aggregates, joins, constraints, rollback, savepoints, indexes,
|
|
19
|
+
timeouts, and recovery for every feature that mutates or reads data.
|
|
20
|
+
|
|
21
|
+
## Query review checklist
|
|
22
|
+
|
|
23
|
+
For each query shape, record schema, indexes, bind types, expected rows,
|
|
24
|
+
expected ordering, transaction isolation, and error behavior. Test empty,
|
|
25
|
+
single-row, duplicate, `NULL`, and large-result cases. Explicitly order results
|
|
26
|
+
when the application requires order; relational results are not inherently
|
|
27
|
+
ordered.
|
|
28
|
+
|
|
29
|
+
Review:
|
|
30
|
+
|
|
31
|
+
* projections and aliases;
|
|
32
|
+
* boolean precedence and `NULL` truth tables;
|
|
33
|
+
* inner, left, and multi-table joins;
|
|
34
|
+
* grouping, aggregate input, and `HAVING`;
|
|
35
|
+
* limits and offsets at boundaries;
|
|
36
|
+
* conflict/upsert behavior and affected-row counts;
|
|
37
|
+
* casts, defaults, and constraint errors; and
|
|
38
|
+
* snapshot visibility during concurrent writes.
|
|
39
|
+
|
|
40
|
+
## Application migration from SQLite
|
|
41
|
+
|
|
42
|
+
Start with a schema dump and a representative query/migration inventory. Run
|
|
43
|
+
the application test suite against RubyDB, not only a few hand-written
|
|
44
|
+
queries. Review pragmas, virtual tables, FTS, extensions, custom functions,
|
|
45
|
+
file-format assumptions, recursive queries, date/time behavior, collations,
|
|
46
|
+
and error handling. These areas are not included merely because the common
|
|
47
|
+
profile looks SQLite-like.
|
|
48
|
+
|
|
49
|
+
Never point RubyDB at an existing SQLite file and expect it to open. Migrate
|
|
50
|
+
through an explicit export/import process with checksums, row counts, and
|
|
51
|
+
application-level verification.
|
|
52
|
+
|
|
53
|
+
## SQL change workflow
|
|
54
|
+
|
|
55
|
+
Add a contract example under `spec/sql`, parser tests, execution tests, failure
|
|
56
|
+
tests, and adapter coverage when relevant. Update the compatibility page and
|
|
57
|
+
release notes. Add a regression for every bug. If semantics are intentionally
|
|
58
|
+
different from another database, document the difference with a migration
|
|
59
|
+
recommendation.
|
|
60
|
+
|
|
61
|
+
## Safe examples
|
|
62
|
+
|
|
63
|
+
```sql
|
|
64
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
65
|
+
id INTEGER PRIMARY KEY,
|
|
66
|
+
email TEXT NOT NULL UNIQUE,
|
|
67
|
+
active BOOLEAN DEFAULT TRUE
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
INSERT INTO users (email, active) VALUES (?, ?);
|
|
71
|
+
|
|
72
|
+
SELECT active, COUNT(*) AS total
|
|
73
|
+
FROM users
|
|
74
|
+
WHERE email IS NOT NULL
|
|
75
|
+
GROUP BY active
|
|
76
|
+
HAVING COUNT(*) > 0
|
|
77
|
+
ORDER BY active;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use bound parameters from Ruby or ActiveRecord. Do not construct SQL by
|
|
81
|
+
concatenating user input.
|
|
82
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# RubyDB SQL compatibility
|
|
2
|
+
|
|
3
|
+
RubyDB supports a deliberately documented SQL dialect. It includes a tested
|
|
4
|
+
SQLite-style compatibility profile for common new Ruby/Rails applications (see
|
|
5
|
+
`sqlite-compatibility.md`), but this is not a claim of complete SQLite,
|
|
6
|
+
PostgreSQL, or MySQL compatibility.
|
|
7
|
+
|
|
8
|
+
Supported and tested statements include:
|
|
9
|
+
|
|
10
|
+
- `SELECT` with projections, `WHERE`, ordering, limits, offsets, built-in
|
|
11
|
+
expressions, and `COUNT`, `SUM`, `AVG`, `MIN`, and `MAX` aggregates (including
|
|
12
|
+
`DISTINCT` aggregate arguments) with
|
|
13
|
+
`GROUP BY` and `HAVING`
|
|
14
|
+
- window ranking functions `ROW_NUMBER`, `RANK`, and `DENSE_RANK`, plus
|
|
15
|
+
partition-wide and explicit `ROWS`-framed aggregate windows using
|
|
16
|
+
`OVER (PARTITION BY ... ORDER BY ...)`
|
|
17
|
+
- `UNION`, `UNION ALL`, `INTERSECT`, and `EXCEPT` for compatible SELECT
|
|
18
|
+
projections
|
|
19
|
+
- non-correlated scalar subqueries, `IN (SELECT ...)`, and `EXISTS (SELECT ...)`
|
|
20
|
+
predicates
|
|
21
|
+
- materialized non-recursive and bounded recursive `WITH` common table
|
|
22
|
+
expressions
|
|
23
|
+
- `INSERT`, `UPDATE`, and `DELETE`, including multi-row `VALUES`,
|
|
24
|
+
`ON CONFLICT DO NOTHING`, and targeted `ON CONFLICT (...) DO UPDATE SET ...`
|
|
25
|
+
with `excluded.column`
|
|
26
|
+
- `CREATE TABLE` and `DROP TABLE`, including primary keys, unique constraints,
|
|
27
|
+
checks, foreign keys, and referential actions
|
|
28
|
+
- `CREATE INDEX`/`CREATE UNIQUE INDEX` and `DROP INDEX`
|
|
29
|
+
- `ALTER TABLE` add/drop columns and constraints
|
|
30
|
+
- `CREATE`/`DROP DATABASE`, `CREATE`/`DROP SCHEMA`, and `CREATE`/`DROP VIEW`
|
|
31
|
+
- supported trigger metadata DDL: `CREATE TRIGGER ... EXECUTE FUNCTION ...`
|
|
32
|
+
- `BEGIN`, `COMMIT`, `ROLLBACK`, `SAVEPOINT`, `ROLLBACK TO SAVEPOINT`, and
|
|
33
|
+
`RELEASE SAVEPOINT`
|
|
34
|
+
- `EXPLAIN`, `EXPLAIN ANALYZE`, and `VACUUM`
|
|
35
|
+
|
|
36
|
+
Unsupported syntax must fail with a parser or execution error. RubyDB does not
|
|
37
|
+
promise arbitrary SQL extensions, PostgreSQL wire-level compatibility, or
|
|
38
|
+
feature parity with another database engine. The executable contract is the
|
|
39
|
+
integration coverage under `spec/`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# SQL data types
|
|
2
|
+
|
|
3
|
+
The documented RubyDB types are `INTEGER`, `BIGINT`, `SMALLINT`, `FLOAT`,
|
|
4
|
+
`DECIMAL`, `BOOLEAN`, `TEXT`, `VARCHAR`, `BLOB`, `DATE`, `TIME`, `TIMESTAMP`,
|
|
5
|
+
`JSON`, and `UUID`. Type conversion, nullability, defaults, and constraint
|
|
6
|
+
behavior are validated through the SQL and Rails suites.
|
|
7
|
+
|
|
8
|
+
RubyDB does not claim storage or coercion compatibility with every other SQL
|
|
9
|
+
engine. Preserve types explicitly in migrations and test application boundary
|
|
10
|
+
values, nulls, booleans, timestamps, decimals, JSON, and binary data.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# SQL functions
|
|
2
|
+
|
|
3
|
+
The tested function surface includes `COUNT`, `SUM`, `AVG`, `MIN`, `MAX`,
|
|
4
|
+
`LOWER`, `UPPER`, `LENGTH`, `SUBSTR`, `CONCAT`, `COALESCE`, and `NULLIF`, plus
|
|
5
|
+
the documented window ranking and aggregate functions.
|
|
6
|
+
|
|
7
|
+
Function null behavior and return types are part of the compatibility contract.
|
|
8
|
+
Do not assume a PostgreSQL, MySQL, or SQLite extension exists because a function
|
|
9
|
+
has the same name; unsupported functions must be reported explicitly.
|
data/docs/sql/joins.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# SQL joins
|
|
2
|
+
|
|
3
|
+
RubyDB supports qualified `INNER`, `LEFT [OUTER]`, `RIGHT`, `FULL [OUTER]`, and
|
|
4
|
+
`CROSS JOIN` forms with `ON` predicates in the documented dialect. Outer joins
|
|
5
|
+
preserve unmatched rows with null-extended columns.
|
|
6
|
+
|
|
7
|
+
Use explicit table qualification when columns are ambiguous. Validate join
|
|
8
|
+
cardinality, null behavior, ordering, grouping, and transaction visibility with
|
|
9
|
+
representative data. Join reordering is limited to safe inner-join plans.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# SQL operators and predicates
|
|
2
|
+
|
|
3
|
+
The documented surface includes arithmetic, comparison, boolean `AND`/`OR` and
|
|
4
|
+
`NOT`, `IS NULL`/`IS NOT NULL`, `BETWEEN`, `IN`, `EXISTS`, `LIKE`, `ILIKE`, and
|
|
5
|
+
three-valued null behavior covered by the SQL tests.
|
|
6
|
+
|
|
7
|
+
Use bound parameters for user input. Test false, null, empty string, numeric
|
|
8
|
+
precision, and mixed-type values explicitly; similar syntax across SQL engines
|
|
9
|
+
does not guarantee identical semantics.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# SQLite compatibility profile
|
|
2
|
+
|
|
3
|
+
RubyDB now maintains an explicit SQLite-style compatibility profile for new
|
|
4
|
+
Ruby and Rails applications. The profile is tested by
|
|
5
|
+
`spec/sqlite_compatibility_spec.rb` and covers the common application surface:
|
|
6
|
+
|
|
7
|
+
- `CREATE TABLE IF NOT EXISTS`, integer primary keys with `AUTOINCREMENT`,
|
|
8
|
+
defaults, `NOT NULL`, and `UNIQUE`
|
|
9
|
+
- CRUD, parameter binding through the Rails connection, transactions, and
|
|
10
|
+
rollback
|
|
11
|
+
- `WHERE`, `IS NULL`/boolean predicates, ordering, `LIMIT`/`OFFSET`, joins,
|
|
12
|
+
grouped aggregates, and `HAVING`
|
|
13
|
+
- targeted `ON CONFLICT ... DO UPDATE` upserts
|
|
14
|
+
- ActiveRecord schema inspection through the embedded adapter
|
|
15
|
+
|
|
16
|
+
This is useful for applications written against the documented RubyDB surface,
|
|
17
|
+
but it is not a complete replacement for the SQLite library. SQLite pragmas,
|
|
18
|
+
virtual tables, FTS, recursive query edge cases, extension APIs, file-format
|
|
19
|
+
compatibility, and every SQLite function/error behavior remain unsupported or
|
|
20
|
+
unverified. An existing SQLite application must run its own migration and
|
|
21
|
+
query suite before migration.
|
data/docs/sql/syntax.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# SQL syntax
|
|
2
|
+
|
|
3
|
+
Statements are parsed by RubyDB's lexer and parser and executed through the
|
|
4
|
+
planner. The supported statements include `SELECT`, `INSERT`, `UPDATE`,
|
|
5
|
+
`DELETE`, table/index/schema/view DDL, transactions/savepoints, `EXPLAIN`, and
|
|
6
|
+
`VACUUM` as listed in [compatibility](compatibility.md).
|
|
7
|
+
|
|
8
|
+
Use semicolons for multiple statements only where the client path supports
|
|
9
|
+
them. Identifiers may be quoted with double quotes or backticks. Unsupported
|
|
10
|
+
syntax fails with a parser or execution error; it is never silently ignored.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# SQL transactions
|
|
2
|
+
|
|
3
|
+
RubyDB supports `BEGIN`, `COMMIT`, `ROLLBACK`, `SAVEPOINT`, `ROLLBACK TO
|
|
4
|
+
SAVEPOINT`, and `RELEASE SAVEPOINT`. Commits coordinate MVCC, locks, row
|
|
5
|
+
mutation, WAL, and durable acknowledgement.
|
|
6
|
+
|
|
7
|
+
Keep transactions short enough for the workload. Long-running readers can
|
|
8
|
+
retain old versions and delay vacuum; deadlock victims must retry the
|
|
9
|
+
application unit. Validate transaction behavior after restart and under
|
|
10
|
+
concurrency.
|
|
@@ -0,0 +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
|
+
|
data/exe/rubydb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# RubyDB executable - This is the gem's main executable that gets installed
|
|
5
|
+
# when the gem is installed. It delegates to bin/rubydb.
|
|
6
|
+
|
|
7
|
+
# This file is the entry point that RubyGems uses when the gem is installed.
|
|
8
|
+
# It allows users to run `rubydb` from anywhere after `gem install rubydb`.
|
|
9
|
+
|
|
10
|
+
require_relative "../lib/rubydb"
|
|
11
|
+
require_relative "../lib/rubydb/cli/application"
|
|
12
|
+
|
|
13
|
+
# Load and execute the CLI application
|
|
14
|
+
begin
|
|
15
|
+
RubyDB::CLI::Application.start(ARGV)
|
|
16
|
+
rescue Interrupt
|
|
17
|
+
puts "\nInterrupted. Exiting..."
|
|
18
|
+
exit 0
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
$stderr.puts "Error: #{e.message}"
|
|
21
|
+
$stderr.puts e.backtrace if ENV["RUBYDB_DEBUG"]
|
|
22
|
+
exit 1
|
|
23
|
+
end
|