From 8dc11f9940c55b12488ab2291d682e44d4fdeb6f Mon Sep 17 00:00:00 2001 From: Emi Matchu Date: Thu, 29 Feb 2024 14:30:33 -0800 Subject: [PATCH] Create `rails public_data:commit` task, to share public data dumps I'm starting to port over the functionality that was previously just, me running `yarn db:export:public-data` in `impress-2020` and committing it to Git LFS every time. My immediate motivation is that the `impress-2020` git repository is getting weirdly large?? Idk how these 40MB files have blown up to a solid 16GB of Git LFS data (we don't have THAT many!!!), but I guess there's something about Git LFS's architecture and disk usage that I'm not understanding. So, let's move to a simpler system in which we don't bind the public data to the codebase, but instead just regularly dump it in production and make it available for download. This change adds the `rails public_data:commit` task, which when run in production will make the latest available at `https://impress.openneo.net/public-data/latest.sql.gz`, and will also store a running log of previous dumps, viewable at `https://impress.openneo.net/public-data/`. Things left to do: 1. Create a `rails public_data:pull` task, to download `latest.sql.gz` and import it into the local development database. 2. Set up a cron job to dump this out regularly, idk maybe weekly? That will grow, but not very fast (about 2GB per year), and we can add logic to rotate out old ones if it starts to grow too far. (If we wanted to get really intricate, we could do like, daily for the past week, then weekly for the past 3 months, then monthly for the past year, idk. There must be tools that do this!) --- .gitignore | 2 + Gemfile | 3 + Gemfile.lock | 6 ++ config/environments/development.rb | 4 ++ config/environments/production.rb | 4 ++ deploy/deploy.yml | 6 ++ deploy/files/sites-available/impress.conf | 4 ++ deploy/setup.yml | 7 +++ lib/tasks/public_data.rake | 67 ++++++++++++++++++++++ vendor/cache/e2mmap-0.1.0.gem | Bin 0 -> 7680 bytes vendor/cache/shell-0.8.1.gem | Bin 0 -> 18432 bytes vendor/cache/sync-0.5.0.gem | Bin 0 -> 8704 bytes 12 files changed, 103 insertions(+) create mode 100644 lib/tasks/public_data.rake create mode 100644 vendor/cache/e2mmap-0.1.0.gem create mode 100644 vendor/cache/shell-0.8.1.gem create mode 100644 vendor/cache/sync-0.5.0.gem diff --git a/.gitignore b/.gitignore index 183ccfbd..26c17459 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ tmp/**/* /app/assets/builds/* !/app/assets/builds/.keep +/public/public-data + /node_modules .pnp.* diff --git a/Gemfile b/Gemfile index fe320aec..4ccff860 100644 --- a/Gemfile +++ b/Gemfile @@ -79,6 +79,9 @@ gem "stackprof", "~> 0.2.25" gem "sentry-ruby", "~> 5.12" gem "sentry-rails", "~> 5.12" +# For tasks that use shell commands. +gem "shell", "~> 0.8.1" + # For automated testing. group :test do gem 'sqlite3', '~> 1.7' diff --git a/Gemfile.lock b/Gemfile.lock index 56689f5b..14075c2f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -139,6 +139,7 @@ GEM railties (>= 3.2) drb (2.2.0) ruby2_keywords + e2mmap (0.1.0) erubi (1.12.0) execjs (2.9.1) falcon (0.43.0) @@ -316,6 +317,9 @@ GEM sentry-ruby (~> 5.16.1) sentry-ruby (5.16.1) concurrent-ruby (~> 1.0, >= 1.0.2) + shell (0.8.1) + e2mmap + sync sprockets (4.2.1) concurrent-ruby (~> 1.0) rack (>= 2.2.4, < 4) @@ -327,6 +331,7 @@ GEM mini_portile2 (~> 2.8.0) stackprof (0.2.26) stringio (3.1.0) + sync (0.5.0) temple (0.10.3) terser (1.2.0) execjs (>= 0.3.0, < 3) @@ -385,6 +390,7 @@ DEPENDENCIES sass-rails (~> 6.0) sentry-rails (~> 5.12) sentry-ruby (~> 5.12) + shell (~> 0.8.1) sprockets (~> 4.2) sqlite3 (~> 1.7) stackprof (~> 0.2.25) diff --git a/config/environments/development.rb b/config/environments/development.rb index 6eac4c70..dbdfcab7 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -112,4 +112,8 @@ Rails.application.configure do # we keep this in a long-term location instead!) config.neopets_media_archive_root = Rails.root / "tmp" / "neopets_media_archive" / "development" + + # When developing the `public_data:commit` command, save to the local `tmp` + # folder. (In production, we keep this in a long-term location instead!) + config.public_data_root = Rails.root / "tmp" / "public_data" end diff --git a/config/environments/production.rb b/config/environments/production.rb index 20858d10..1a11dbb1 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -130,4 +130,8 @@ Rails.application.configure do # Save the Neopets Media Archive in `/var/lib/neopets-media-archive`, a # long-term storage location. config.neopets_media_archive_root = "/var/lib/neopets-media-archive" + + # Save our public data exports in `public/public-data`. (This should be + # symlinked to a shared folder persisted across all versions.) + config.public_data_root = Rails.root / "public" / "public-data" end diff --git a/deploy/deploy.yml b/deploy/deploy.yml index d6a5dd61..e40a4e5f 100644 --- a/deploy/deploy.yml +++ b/deploy/deploy.yml @@ -51,6 +51,12 @@ - "--exclude=.git" - "--filter=':- .gitignore'" + - name: Link the public-data folder to the shared public-data folder + file: + src: "{{ remote_project_root }}/shared/public-data" + dest: "{{ remote_app_root }}/public/public-data" + state: link + - name: Configure Bundler to run in deployment mode command: chdir: "{{ remote_app_root }}" diff --git a/deploy/files/sites-available/impress.conf b/deploy/files/sites-available/impress.conf index 91cbcb0c..3401a70b 100644 --- a/deploy/files/sites-available/impress.conf +++ b/deploy/files/sites-available/impress.conf @@ -33,6 +33,10 @@ server { add_header ETag ""; } + location /public-data/ { + autoindex on; + } + # On status 503, return the maintenance page. (We'll trigger this ourselves # in the @app location, if $maintenance is on.) error_page 503 /maintenance.html; diff --git a/deploy/setup.yml b/deploy/setup.yml index 2646fbe9..2c30014f 100644 --- a/deploy/setup.yml +++ b/deploy/setup.yml @@ -275,6 +275,13 @@ - Reload systemctl - Restart impress + - name: Create the shared public-data folder + become_user: impress + file: + dest: /srv/impress/shared/public-data + mode: "755" + state: directory + - name: Create service file for impress copy: src: files/impress.service diff --git a/lib/tasks/public_data.rake b/lib/tasks/public_data.rake new file mode 100644 index 00000000..d4416dc0 --- /dev/null +++ b/lib/tasks/public_data.rake @@ -0,0 +1,67 @@ +require "open3" + +desc "Tools to save and import DTI's public modeling data" +namespace :public_data do + desc "Save the local database's public data to a local file" + task :commit, [:name] => :environment do |_, args| + if Rails.env.development? + puts "NOTE: The `public_data:commit` task is primarily meant to be " + + "run in production, to create public data files we can copy to our " + + "development machines via `public_data:pull`. I'll still run it " + + "locally and save to #{Rails.configuration.public_data_root}, though!" + end + + config = ApplicationRecord.connection_db_config.configuration_hash + + # Generate a filename from the current time, and the option name argument + # provided to the command (e.g. `rails public_data:commit[scheduled]`). + timestamp = Time.now.utc.iso8601.gsub(':', '_') + name = args.fetch(:name, "manual") + filename = "#{timestamp}-#{name}.sql.gz" + dest_path = Rails.configuration.public_data_root / filename + + args = [] + + # The connection details for our database! + args << "--host=#{config[:host]}" if config[:host] + args << "--user=#{config[:username]}" if config[:username] + args << "--password=#{config[:password]}" if config[:password] + + # Don't lock the database to do it! + args << "--single-transaction" + + # Dump the public data tables from the primary database. + args << config.fetch(:database) + args += %w(species colors zones) # manual constants + args += %w(alt_styles items parents_swf_assets pet_states pet_types + swf_assets) # from modeling + + # Set up a shell, and register the commands we need. + Shell.def_system_command("mysqldump") + Shell.def_system_command("gzip") + sh = Shell.new + + # Ensure the output directory exists. + dest_path.dirname.mkpath + + # Run mysqldump, pipe it into gzip, and output to the destination file. + sh.mysqldump(*args) | sh.gzip("-c") > dest_path.to_s + puts "Saved dump to #{dest_path}" + + # Link this latest dump as `latest.sql.gz`. + latest_path = Rails.configuration.public_data_root / "latest.sql.gz" + File.unlink(latest_path) if File.exist?(latest_path) + File.symlink(dest_path, latest_path) + puts "Linked dump to #{latest_path}" + end + + desc "Pull and import the latest public data from production (dev only)" + task :pull do + unless Rails.env.development? + raise "Can only pull public data in development mode! This helps us " + + "ensure we won't overwrite the production database accidentally." + end + + raise NotImplementedError, "TODO!" + end +end diff --git a/vendor/cache/e2mmap-0.1.0.gem b/vendor/cache/e2mmap-0.1.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..c5d26939849b22dfa667f1d8c0b24dfe19be1fe4 GIT binary patch literal 7680 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 literal 0 HcmV?d00001 diff --git a/vendor/cache/shell-0.8.1.gem b/vendor/cache/shell-0.8.1.gem new file mode 100644 index 0000000000000000000000000000000000000000..d7d8bf56fa03d1c734630cf4bda5c7091b256c68 GIT binary patch literal 18432 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 literal 0 HcmV?d00001 diff --git a/vendor/cache/sync-0.5.0.gem b/vendor/cache/sync-0.5.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..1aa977b6701e0382d1e6e84190d8838a69e4ec1a GIT binary patch literal 8704 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 RWBlELzdP`E2may?{2N3QuL}SG literal 0 HcmV?d00001