提问人:Dan Lincoln 提问时间:11/17/2023 最后编辑:Dan Lincoln 更新时间:11/18/2023 访问量:61
如何最好地调试失败的 ruby 迁移?
How to best debug a failed ruby migration?
问:
我的团队最近继承了一个遗留的 ruby 代码库,它有点混乱。(我自己不是 ruby 开发人员,我们团队中唯一的 ruby 开发人员已经在公司工作了 >6 个月,所以我们非常不了解我们的深度)
我们不得不添加一个 db 列,该列在开发和暂存中按预期工作,但是在部署到 prod 时,我们在启动 db:migrate rake 过程时遇到了问题(迁移和消息如下)。
暂存部署似乎使用了elastic beanstalk,其中prod部署由codedeploy直接管理到EC2实例中,因此肯定存在一些差异(我希望我们知道为什么:/ )。
任何关于从哪里开始寻找的想法将不胜感激
class AddListPriceIncVatAmountToVariants < ActiveRecord::Migration[6.0]
def change
add_column :variants, :list_price_inc_vat_amount, :decimal, null: false, default: 0.0
add_index :variants, :list_price_inc_vat_amount
end
end
** Invoke db:migrate (first_time)
** Invoke db:load_config (first_time)
** Invoke environment (first_time)
** Execute environment
rake aborted!
ArgumentError: comparison of Integer with nil failed
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/logger_thread_safe_level.rb:19:in `>='
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/logger_thread_safe_level.rb:19:in `debug?'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/agent/agent_logger.rb:86:in `format_and_send'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/agent/agent_logger.rb:44:in `debug'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/agent/memory_logger.rb:53:in `block in dump'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/agent/memory_logger.rb:52:in `each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/agent/memory_logger.rb:52:in `dump'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/agent/agent_logger.rb:178:in `gather_startup_logs'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/agent/agent_logger.rb:24:in `initialize'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/control/private_instance_methods.rb:30:in `new'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/control/private_instance_methods.rb:30:in `create_logger'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/new_relic/control/instance_methods.rb:58:in `init_plugin'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/newrelic_rpm-8.15.0/lib/newrelic_rpm.rb:34:in `block in <class:Railtie>'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:32:in `instance_exec'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:32:in `run'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:61:in `block in run_initializers'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:228:in `block in tsort_each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:422:in `block (2 levels) in each_strongly_connected_component_from'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:422:in `block (2 levels) in each_strongly_connected_component_from'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:431:in `each_strongly_connected_component_from'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:421:in `block in each_strongly_connected_component_from'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:50:in `each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:50:in `tsort_each_child'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:415:in `call'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:415:in `each_strongly_connected_component_from'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:421:in `block in each_strongly_connected_component_from'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:50:in `each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:50:in `tsort_each_child'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:415:in `call'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:415:in `each_strongly_connected_component_from'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:349:in `block in each_strongly_connected_component'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:347:in `each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:347:in `call'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:347:in `each_strongly_connected_component'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:226:in `tsort_each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:205:in `tsort_each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:60:in `run_initializers'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/application.rb:363:in `initialize!'
/home/ubuntu/platform-api/config/environment.rb:5:in `<main>'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bootsnap-1.7.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bootsnap-1.7.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bootsnap-1.7.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bootsnap-1.7.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bootsnap-1.7.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:34:in `require'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/dependencies.rb:324:in `block in require'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/dependencies.rb:291:in `load_dependency'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/dependencies.rb:324:in `require'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/application.rb:339:in `require_environment!'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/application.rb:523:in `block in run_tasks_blocks'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:281:in `block in execute'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:281:in `each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:281:in `execute'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/monitor.rb:235:in `mon_synchronize'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:241:in `each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:241:in `invoke_prerequisites'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/monitor.rb:235:in `mon_synchronize'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:241:in `each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:241:in `invoke_prerequisites'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/2.6.0/monitor.rb:235:in `mon_synchronize'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:188:in `invoke'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:160:in `invoke_task'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:116:in `each'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:116:in `block in top_level'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:125:in `run_with_threads'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:110:in `top_level'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:83:in `block in run'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:186:in `standard_exception_handling'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/application.rb:80:in `run'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rake-13.0.3/exe/rake:27:in `<top (required)>'
/home/ubuntu/.rbenv/versions/2.6.6/bin/rake:23:in `load'
/home/ubuntu/.rbenv/versions/2.6.6/bin/rake:23:in `<top (required)>'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/cli/exec.rb:63:in `load'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/cli/exec.rb:63:in `kernel_load'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/cli/exec.rb:28:in `run'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/cli.rb:494:in `exec'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/cli.rb:30:in `dispatch'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/cli.rb:24:in `start'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/exe/bundle:49:in `block in <top (required)>'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/lib/bundler/friendly_errors.rb:130:in `with_friendly_errors'
/home/ubuntu/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.2.15/exe/bundle:37:in `<top (required)>'
/home/ubuntu/.rbenv/versions/2.6.6/bin/bundle:23:in `load'
/home/ubuntu/.rbenv/versions/2.6.6/bin/bundle:23:in `<main>'
Tasks: TOP => db:migrate => db:load_config => environment
我们尝试过对生产数据库进行转储,并在本地运行迁移,这一切都顺利完成,因此我们非常有信心这不是数据问题。
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local
# Mount Action Cable outside main process or domain.
# config.action_cable.mount_path = nil
# config.action_cable.url = 'wss://example.com/cable'
config.action_cable.url = ENV['ACTION_CABLE_URL']
config.action_cable.allowed_request_origins = [%r{https://*.<redacted>.com}]
config.action_cable.disable_request_forgery_protection = true
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :info
# Prepend all log lines with the following tags.
config.log_tags = [:request_id]
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
config.cache_store = :redis_cache_store, {
url: Rails.application.config_for(:redis).cache_url,
pool_size: ENV.fetch('RAILS_MAX_THREADS', 20),
pool_timeout: 5
}
config.active_record.cache_versioning = false
# Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "app_production"
config.action_mailer.perform_caching = false
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Use a different logger for distributed setups.
# require 'syslog/logger'
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
if ENV['RAILS_LOG_TO_STDOUT'].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
# Inserts middleware to perform automatic connection switching.
# The `database_selector` hash is used to pass options to the DatabaseSelector
# middleware. The `delay` is used to determine how long to wait after a write
# to send a subsequent read to the primary.
#
# The `database_resolver` class is used by the middleware to determine which
# database is appropriate to use based on the time delay.
#
# The `database_resolver_context` class is used by the middleware to set
# timestamps for the last write to the primary. The resolver uses the context
# class timestamps to determine how long to wait before reading from the
# replica.
#
# By default Rails will store a last write timestamp in the session. The
# DatabaseSelector middleware is designed as such you can define your own
# strategy for connection switching and pass that into the middleware through
# these configuration options.
# config.active_record.database_selector = { delay: 2.seconds }
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
# Loggly
# require 'syslogger'
# config.logger = Syslogger.new("platform-api", Syslog::LOG_PID, Syslog::LOG_LOCAL7)
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
user_name: 'apikey', # This is the string literal 'apikey', NOT the ID of your API key
password: ENV['SENDGRID_API_KEY'], # This is the secret sendgrid API key which was issued during API key creation
domain: '<redacted>.com',
address: 'smtp.sendgrid.net',
port: 587,
authentication: :plain,
enable_starttls_auto: true
}
config.middleware.use ExceptionNotification::Rack,
email: {
email_prefix: Rails.env,
sender_address: "'Exception Notifier' <#{ENV['SENDGRID_EMAIL']}>",
exception_recipients: ['carlo@<redacted>.com']
},
slack: {
webhook_url: ENV['SLACK_WEBHOOK'],
channel: '#platform-api',
additional_parameters: {
mrkdwn: true
}
}
end
答: 暂无答案
评论