From 4d3c1a800b7d0296de6f2cf768236de65eb69ad4 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Thu, 27 Feb 2025 23:13:57 -0800 Subject: [PATCH] Update config files (#189) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update weapon series migration This update fixes MigrateWeaponSeries from 20250218 such that it can be run on an empty database without throwing errors. * Update .gitignore Hide backups and logs directories, since we’ll be storing these in the project folder. Also hide mise’s .local directory. * Change NewRelic log directory Moved from log/ to logs/ * Add rake task for backing up/restoring prod db * Rubocop fixes * Fix error where :preview_state didn’t have an attribute * Add supervisord ini This uses my local paths, so we should try to abstract that away later. * Ignore mise.toml --- .gitignore | 6 +++++- app/models/party.rb | 9 ++++---- config/newrelic.yml | 2 ++ config/puma.rb | 10 ++++----- lib/tasks/database.rake | 42 ++++++++++++++++++++++++++++++++++++++ supervisord/hensei-api.ini | 17 +++++++++++++++ 6 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 lib/tasks/database.rake create mode 100644 supervisord/hensei-api.ini diff --git a/.gitignore b/.gitignore index f26a26e..f469329 100644 --- a/.gitignore +++ b/.gitignore @@ -37,9 +37,12 @@ # Ignore master key for decrypting credentials and more. /config/master.key -# Ignore exported and downloaded files +# Ignore specific directories +/.local /export /download +/backups +/logs .DS_Store @@ -55,3 +58,4 @@ config/application.yml # Ignore AI Codebase-generated files codebase.md +mise.toml diff --git a/app/models/party.rb b/app/models/party.rb index fb88260..f15acff 100644 --- a/app/models/party.rb +++ b/app/models/party.rb @@ -78,6 +78,7 @@ class Party < ApplicationRecord include GranblueEnums # Define preview_state as an enum. + attribute :preview_state, :integer enum :preview_state, { pending: 0, queued: 1, in_progress: 2, generated: 3, failed: 4 } # ActiveRecord Associations @@ -400,7 +401,7 @@ class Party < ApplicationRecord # @return [void] def skills_are_unique validate_uniqueness_of_associations([skill0, skill1, skill2, skill3], - [:skill0, :skill1, :skill2, :skill3], + %i[skill0 skill1 skill2 skill3], :job_skills) end @@ -410,7 +411,7 @@ class Party < ApplicationRecord # @return [void] def guidebooks_are_unique validate_uniqueness_of_associations([guidebook1, guidebook2, guidebook3], - [:guidebook1, :guidebook2, :guidebook3], + %i[guidebook1 guidebook2 guidebook3], :guidebooks) end @@ -438,7 +439,7 @@ class Party < ApplicationRecord def update_element! main_weapon = weapons.detect { |gw| gw.position.to_i == -1 } new_element = main_weapon&.weapon&.element - update_column(:element, new_element) if new_element.present? && self.element != new_element + update_column(:element, new_element) if new_element.present? && element != new_element end ## @@ -449,7 +450,7 @@ class Party < ApplicationRecord # @return [void] def update_extra! new_extra = weapons.any? { |gw| GridWeapon::EXTRA_POSITIONS.include?(gw.position.to_i) } - update_column(:extra, new_extra) if self.extra != new_extra + update_column(:extra, new_extra) if extra != new_extra end ## diff --git a/config/newrelic.yml b/config/newrelic.yml index 9f25061..a9483e0 100644 --- a/config/newrelic.yml +++ b/config/newrelic.yml @@ -25,6 +25,8 @@ common: &default_settings # agent_enabled: false + log_file_path: logs/ + # Logging level for log/newrelic_agent.log log_level: info diff --git a/config/puma.rb b/config/puma.rb index 862807f..a233ec2 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -4,20 +4,20 @@ # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum; this matches the default thread size of Active Record. # -max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } -min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +max_threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 } +min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count } threads min_threads_count, max_threads_count # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch("PORT") { 3000 } +port ENV.fetch('PORT', 3000) # Specifies the `environment` that Puma will run in. # -environment ENV.fetch("RAILS_ENV") { "development" } +environment ENV.fetch('RAILS_ENV') { 'development' } # Specifies the `pidfile` that Puma will use. -pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } +pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' } # Specifies the number of `workers` to boot in clustered mode. # Workers are forked web server processes. If using threads and workers together diff --git a/lib/tasks/database.rake b/lib/tasks/database.rake new file mode 100644 index 0000000..227fb16 --- /dev/null +++ b/lib/tasks/database.rake @@ -0,0 +1,42 @@ +namespace :db do + desc 'Backup remote PostgreSQL database' + task :backup do + remote_host = ENV.fetch('REMOTE_DB_HOST', 'roundhouse.proxy.rlwy.net') + remote_port = ENV.fetch('REMOTE_DB_PORT', '54629') + remote_user = ENV.fetch('REMOTE_DB_USER', 'postgres') + remote_db = ENV.fetch('REMOTE_DB_NAME', 'railway') + password = ENV.fetch('REMOTE_DB_PASSWORD') { raise 'Please set REMOTE_DB_PASSWORD' } + + backup_dir = File.expand_path('backups') + FileUtils.mkdir_p(backup_dir) + backup_file = File.join(backup_dir, "#{Time.now.strftime('%Y%m%d_%H%M%S')}-prod-backup.tar") + + cmd = %W[ + pg_dump -h #{remote_host} -p #{remote_port} -U #{remote_user} -d #{remote_db} -F t + --no-owner --exclude-extension=timescaledb --exclude-extension=timescaledb_toolkit + ].join(' ') + + puts "Backing up remote database to #{backup_file}..." + system({ 'PGPASSWORD' => password }, "#{cmd} > #{backup_file}") + puts 'Backup completed!' + end + + desc 'Restore PostgreSQL database from backup' + task :restore, [:backup_file] => [:environment] do |_, args| + local_user = ENV.fetch('LOCAL_DB_USER', 'justin') + local_db = ENV.fetch('LOCAL_DB_NAME', 'hensei_dev') + + # Use the specified backup file or find the most recent one + backup_dir = File.expand_path('backups') + backup_file = args[:backup_file] || Dir.glob("#{backup_dir}/*-prod-backup.tar").max + + raise 'Backup file not found. Please specify a valid backup file.' unless backup_file && File.exist?(backup_file) + + puts "Restoring database from #{backup_file}..." + system("pg_restore --no-owner --role=#{local_user} --disable-triggers -U #{local_user} -d #{local_db} #{backup_file}") + puts 'Restore completed!' + end + + desc 'Backup remote database and restore locally' + task backup_and_restore: %i[backup restore] +end diff --git a/supervisord/hensei-api.ini b/supervisord/hensei-api.ini new file mode 100644 index 0000000..285a4c4 --- /dev/null +++ b/supervisord/hensei-api.ini @@ -0,0 +1,17 @@ +[program:hensei-api] +command=/opt/homebrew/bin/mise run s +process_name=%(program_name)s +numprocs=1 +directory=/Users/justin/Developer/Granblue/hensei-api +environment=HOME="/Users/justin",MISE_CONFIG_ROOT="/Users/justin/Developer/Granblue/hensei-api",RAILS_ENV="development" +autostart=true +autorestart=unexpected +stopsignal=TERM +user=justin +stdout_logfile=/Users/justin/Developer/Granblue/hensei-api/logs/hensei-api.stdout.log +stdout_logfile_maxbytes=500KB +stdout_logfile_backups=10 +stderr_logfile=/Users/justin/Developer/Granblue/hensei-api/logs/hensei-api.stderr.log +stderr_logfile_maxbytes=500KB +stderr_logfile_backups=10 +serverurl=AUTO