hensei-api/lib/granblue/post_deployment_manager.rb
Justin Edmund c0922203a7
Create pipeline for importing data via PRs (#148)
* Add table for data version and migrate

* Modify migration and re-migrate

* Create data_version.rb

Adds a model for DataVersion

* Add aws-sdk-s3 and create aws_service.rb

AwsService handles streaming game image files from the Granblue Fantasy server to our S3 instance.

* Add importers

The Importer libraries take CSV data and import them into the database for each type. We currently support characters, summons and weapons.

* Add downloaders

Downloaders take Granblue IDs and download images for those items from the Granblue Fantasy server in all relevant sizes.

Downloaders can download to disk or stream the file directly to S3.

* Create data_importer.rb

* Fetches a list of all CSV files present in the updates folder
* Checks which have already been imported
* Sends unimported data to the appropriate Importer to handle

* Create download_manager.rb

Creates an appropriate downloader for each Granblue ID it receives

* Update download_images.rake

Most of this task has been extracted into the Downloader libraries

* Update import_data.rake

* Create deploy.rake

This task is to be run as a post-deploy script. It checks for new unimported data, imports it, then downloads the relevant images to S3 or local disk depending on the parameters provided.

* Update credentials.yml.enc

* Began working on a README and added example CSVs

* Modify importer to handle updates

This way we can also add FLBs and other uncaps easier.

* Updates only require values that will change

When updating a row, fields that don't have a provided value will not be changed

* Rebuild search indices in post deploy

* Clean up logs with LoggingHelper

* More logging adjustments

Trying to get a nice-looking output

* Change some ASCII characters

* Final ASCII changes

* Fix issues with Summon and Weapon importers

* Finish README for contributing
2025-01-13 05:33:04 -08:00

140 lines
3.5 KiB
Ruby

# frozen_string_literal: true
require_relative '../logging_helper'
class PostDeploymentManager
include LoggingHelper
STORAGE_DESCRIPTIONS = {
local: 'to local disk',
s3: 'to S3',
both: 'to local disk and S3'
}.freeze
def initialize(options = {})
@test_mode = options.fetch(:test_mode, false)
@verbose = options.fetch(:verbose, false)
@storage = options.fetch(:storage, :both)
@new_records = Hash.new { |h, k| h[k] = [] }
@updated_records = Hash.new { |h, k| h[k] = [] }
end
def run
import_new_data
display_import_summary
download_images
rebuild_search_indices
display_completion_message
end
private
def import_new_data
log_header 'Importing new data...'
puts "\n"
importer = Granblue::DataImporter.new(
test_mode: @test_mode,
verbose: @verbose
)
process_imports(importer)
end
def process_imports(importer)
importer.process_all_files do |result|
result[:new].each do |type, ids|
@new_records[type].concat(ids)
end
result[:updated].each do |type, ids|
@updated_records[type].concat(ids)
end
end
end
def rebuild_search_indices
log_header 'Rebuilding search indices...', '-'
puts "\n"
[Character, Summon, Weapon, Job].each do |model|
log_verbose "#{model.name}... "
PgSearch::Multisearch.rebuild(model)
log_verbose "✅ done!\n"
end
end
def display_import_summary
if @new_records.size > 0 || @updated_records.size > 0
log_header 'Import Summary', '-'
puts "\n"
display_record_summary('New', @new_records)
display_record_summary('Updated', @updated_records)
else
log_step "\nNo new records imported."
end
end
def display_record_summary(label, records)
records.each do |type, ids|
next if ids.empty?
puts "#{type.capitalize}: #{ids.size} #{label.downcase} records"
puts "IDs: #{ids.inspect}" if @verbose
end
end
def download_images
return if all_records_empty?
if @test_mode
log_step "\nTEST MODE: Would download images for new and updated records..."
else
log_header 'Downloading images...', '+'
end
[@new_records, @updated_records].each do |records|
records.each do |type, ids|
next if ids.empty?
download_type_images(type, ids)
end
end
end
def download_type_images(type, ids)
log_step "\nProcessing new #{type.pluralize} (#{ids.size} records)..."
download_options = {
test_mode: @test_mode,
verbose: @verbose,
storage: @storage
}
ids.each do |id|
download_single_image(type, id, download_options)
end
end
def download_single_image(type, id, options)
action_text = @test_mode ? 'Would download' : 'Downloading'
storage_text = STORAGE_DESCRIPTIONS[options[:storage]]
log_verbose "\n#{action_text} images #{storage_text} for #{type} #{id}...\n"
Granblue::Downloader::DownloadManager.download_for_object(
type,
id,
**options
)
rescue => e
error_message = "Error #{@test_mode ? 'would occur' : 'occurred'} downloading images for #{type} #{id}: #{e.message}"
puts error_message
puts e.backtrace.take(5) if @verbose
end
def display_completion_message
if @test_mode
log_step "\n✓ Test run completed successfully!"
else
log_step "\n✓ Post-deployment tasks completed successfully!"
end
end
def all_records_empty?
@new_records.values.all?(&:empty?) && @updated_records.values.all?(&:empty?)
end
end