diff --git a/Gemfile b/Gemfile index f3a0ec5..c5c6e03 100644 --- a/Gemfile +++ b/Gemfile @@ -99,6 +99,7 @@ gem "avo", ">= 3.2" gem "ransack", "~> 4.1" gem "activerecord-enhancedsqlite3-adapter" +gem "litestream", "~> 0.10.1" # sitepress gem "sitepress-rails", "~> 4.0" @@ -111,6 +112,8 @@ gem "blazer" gem "solid_errors" -gem "solid_queue", "~> 0.2.2" +gem "solid_cache" + +gem "solid_queue", github: "rails/solid_queue", branch: "main" gem "mission_control-jobs", "~> 0.1.1" diff --git a/Gemfile.lock b/Gemfile.lock index ca39c61..9882e49 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,7 +11,7 @@ GIT GIT remote: https://github.com/rails/rails.git - revision: 462e9143189ad46d3f26a52d0c132cf69868aa4f + revision: ad0e3123e186c919973fe9e1cec04272c75dd252 branch: main specs: actioncable (7.2.0.alpha) @@ -105,6 +105,18 @@ GIT thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) +GIT + remote: https://github.com/rails/solid_queue.git + revision: 023f6108754673b80b65c31680a5d6693eedfc21 + branch: main + specs: + solid_queue (0.3.0) + activejob (>= 7.1) + activerecord (>= 7.1) + concurrent-ruby (~> 1.2.2) + fugit (~> 1.10.1) + railties (>= 7.1) + GEM remote: https://rubygems.org/ specs: @@ -220,7 +232,12 @@ GEM rubocop smart_properties erubi (1.12.0) + et-orbi (1.2.11) + tzinfo ffi (1.16.3) + fugit (1.10.1) + et-orbi (~> 1, >= 1.2.7) + raabro (~> 1.4) globalid (1.2.1) activesupport (>= 6.1) heroicon (1.0.0) @@ -287,6 +304,19 @@ GEM listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) + litestream (0.10.1) + logfmt (>= 0.0.10) + sqlite3 + litestream (0.10.1-arm64-darwin) + logfmt (>= 0.0.10) + sqlite3 + litestream (0.10.1-x86_64-darwin) + logfmt (>= 0.0.10) + sqlite3 + litestream (0.10.1-x86_64-linux) + logfmt (>= 0.0.10) + sqlite3 + logfmt (0.0.10) loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -368,6 +398,7 @@ GEM public_suffix (5.0.5) puma (6.4.2) nio4r (~> 2.0) + raabro (1.4.0) racc (1.7.3) rack (3.0.11) rack-session (2.0.0) @@ -447,6 +478,10 @@ GEM sitepress-core (= 4.0.2) sprockets-rails (>= 2.0.0) smart_properties (1.17.0) + solid_cache (0.6.0) + activejob (>= 7) + activerecord (>= 7) + railties (>= 7) solid_errors (0.4.2) actionmailer (~> 7.0) actionpack (~> 7.0) @@ -454,8 +489,6 @@ GEM activerecord (~> 7.0) activesupport (~> 7.0) railties (~> 7.0) - solid_queue (0.2.2) - rails (~> 7.1) sorbet-runtime (0.5.11372) sprockets (4.2.1) concurrent-ruby (~> 1.0) @@ -555,6 +588,7 @@ DEPENDENCIES jsbundling-rails kamal letter_opener + litestream (~> 0.10.1) magic_test! markdown-rails (~> 2.1) mission_control-jobs (~> 0.1.1) @@ -568,8 +602,9 @@ DEPENDENCIES ruby-lsp-rails selenium-webdriver sitepress-rails (~> 4.0) + solid_cache solid_errors - solid_queue (~> 0.2.2) + solid_queue! sqlite3 (~> 1.4) standard (>= 1.35.1) stimulus-rails diff --git a/config/application.rb b/config/application.rb index b1e8be3..f84746e 100644 --- a/config/application.rb +++ b/config/application.rb @@ -23,5 +23,18 @@ class Application < Rails::Application # # config.time_zone = "Central Time (US & Canada)" # config.eager_load_paths << Rails.root.join("extras") + + # Use Solid Queue as the Active Job backend + config.active_job.queue_adapter = :solid_queue + config.solid_queue.connects_to = {database: {writing: :queue, reading: :queue}} + + # Use Solid Cache Store as the cache store + config.cache_store = :solid_cache_store + + # Use a separate database for error monitoring + config.solid_errors.connects_to = {database: {writing: :errors, reading: :errors}} + # config.solid_errors.send_emails = true + # config.solid_errors.email_from = "errors@hello.com" + # config.solid_errors.email_to = "me@hello.com" end end diff --git a/config/database.yml b/config/database.yml index 796466b..b07f83a 100644 --- a/config/database.yml +++ b/config/database.yml @@ -4,22 +4,56 @@ # Ensure the SQLite 3 gem is defined in your Gemfile # gem "sqlite3" # +# DEFAULT CONNECTION CONFIGURATION default: &default adapter: sqlite3 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 -development: +# DATABASE CONFIGURATIONS +primary: &primary + <<: *default + database: storage/<%= Rails.env %>.sqlite3 + +queue: &queue + <<: *default + migrations_paths: db/queue_migrate + database: storage/<%= Rails.env %>-queue.sqlite3 + +cache: &cache + <<: *default + migrations_paths: db/cache_migrate + database: storage/<%= Rails.env %>-cache.sqlite3 + +errors: &errors <<: *default - database: storage/development.sqlite3 + migrations_paths: db/errors_migrate + database: storage/<%= Rails.env %>-errors.sqlite3 + +# ENVIRONMENT CONFIGURATIONS +development: + primary: *primary + queue: *queue + cache: *cache + errors: *errors # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - <<: *default - database: storage/test.sqlite3 + primary: *primary + queue: *queue + cache: *cache + errors: *errors +# SQLite3 write its data on the local filesystem, as such it requires +# persistent disks. If you are deploying to a managed service, you should +# make sure it provides disk persistence, as many don't. +# +# Similarly, if you deploy your application as a Docker container, you must +# ensure the database is located in a persisted volume. production: - <<: *default - database: storage/production.sqlite3 + primary: *primary + queue: *queue + cache: *cache + errors: *errors diff --git a/config/environments/development.rb b/config/environments/development.rb index c126173..5ca3840 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -23,7 +23,6 @@ config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true - config.cache_store = :memory_store config.public_file_server.headers = {"Cache-Control" => "public, max-age=#{2.days.to_i}"} else config.action_controller.perform_caching = false diff --git a/config/environments/production.rb b/config/environments/production.rb index c773ac7..b08511b 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -60,11 +60,7 @@ # want to log everything, set the level to "debug". config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") - # Use a different cache store in production. - # config.cache_store = :mem_cache_store - # Use a real queuing backend for Active Job (and separate queues per environment). - config.active_job.queue_adapter = :solid_queue # config.active_job.queue_name_prefix = "daisy_on_rails_production" config.action_mailer.perform_caching = false diff --git a/config/environments/test.rb b/config/environments/test.rb index 06b5e2f..06d56fe 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -25,6 +25,8 @@ config.action_controller.perform_caching = false config.cache_store = :null_store + config.active_job.queue_adapter = :test + # Render exception templates for rescuable exceptions and raise for other exceptions. config.action_dispatch.show_exceptions = :rescuable diff --git a/config/initializers/litesream.rb b/config/initializers/litesream.rb new file mode 100644 index 0000000..1920896 --- /dev/null +++ b/config/initializers/litesream.rb @@ -0,0 +1,33 @@ +# Use this hook to configure the litestream-ruby gem. +# All configuration options will be available as environment variables, e.g. +# config.replica_bucket becomes LITESTREAM_REPLICA_BUCKET +# This allows you to configure Litestream using Rails encrypted credentials, +# or some other mechanism where the values are only avaialble at runtime. + +Litestream.configure do |config| + # An example of using Rails encrypted credentials to configure Litestream. + litestream_credentials = Rails.application.credentials.litestream + + # Replica-specific bucket location. + # This will be your bucket's URL without the `https://` prefix. + # For example, if you used DigitalOcean Spaces, your bucket URL could look like: + # https://myapp.fra1.digitaloceanspaces.com + # And so you should set your `replica_bucket` to: + # myapp.fra1.digitaloceanspaces.com + # Litestream supports Azure Blog Storage, Backblaze B2, DigitalOcean Spaces, + # Scaleway Object Storage, Google Cloud Storage, Linode Object Storage, and + # any SFTP server. + # In this example, we are using Rails encrypted credentials to store the URL to + # our storage provider bucket. + config.replica_bucket = litestream_credentials&.replica_bucket + + # Replica-specific authentication key. + # Litestream needs authentication credentials to access your storage provider bucket. + # In this example, we are using Rails encrypted credentials to store the access key ID. + config.replica_key_id = litestream_credentials&.replica_key_id + + # Replica-specific secret key. + # Litestream needs authentication credentials to access your storage provider bucket. + # In this example, we are using Rails encrypted credentials to store the secret access key. + config.replica_access_key = litestream_credentials&.replica_access_key +end diff --git a/config/puma.rb b/config/puma.rb index afa809b..20ebbd7 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -2,34 +2,58 @@ # are invoked here are part of Puma's configuration DSL. For more information # about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. -# Puma can serve each request in a thread from an internal thread pool. -# The `threads` method setting takes two numbers: a minimum and maximum. -# Any libraries that use thread pools should be configured to match -# 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 } -threads min_threads_count, max_threads_count - -# Specifies that the worker count should equal the number of processors in production. -if ENV["RAILS_ENV"] == "production" - require "concurrent-ruby" - worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { Concurrent.physical_processor_count }) - workers worker_count if worker_count > 1 -end +# Puma starts a configurable number of processes (workers) and each process +# serves each request in a thread from an internal thread pool. +# +# The ideal number of threads per worker depends both on how much time the +# application spends waiting for IO operations and on how much you wish to +# to prioritize throughput over latency. +# +# As a rule of thumb, increasing the number of threads will increase how much +# traffic a given process can handle (throughput), but due to CRuby's +# Global VM Lock (GVL) it has diminishing returns and will degrade the +# response time (latency) of the application. +# +# The default is set to 3 threads as it's deemed a decent compromise between +# throughput and latency for the average Rails application. +# +# Any libraries that use a connection pool or another resource pool should +# be configured to provide at least as many connections as the number of +# threads. This includes Active Record's `pool` parameter in `database.yml`. +threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) +threads threads_count, threads_count -# Specifies the `worker_timeout` threshold that Puma will use to wait before -# terminating a worker in development environments. -worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" +# Specifies the `environment` that Puma will run in. +rails_env = ENV.fetch("RAILS_ENV", "development") +environment rails_env -# Specifies the `port` that Puma will listen on to receive requests; default is 3000. -port ENV.fetch("PORT") { 3000 } +case rails_env +when "production" + # If you are running more than 1 thread per process, the workers count + # should be equal to the number of processors (CPU cores) in production. + # + # It defaults to 1 because it's impossible to reliably detect how many + # CPU cores are available. Make sure to set the `WEB_CONCURRENCY` environment + # variable to match the number of processors. + workers_count = Integer(ENV.fetch("WEB_CONCURRENCY", 1)) + workers workers_count if workers_count > 1 -# Specifies the `environment` that Puma will run in. -environment ENV.fetch("RAILS_ENV") { "development" } + preload_app! +when "development" + # Specifies a very generous `worker_timeout` so that the worker + # isn't killed by Puma when suspended by a debugger. + worker_timeout 3600 +end -# Specifies the `pidfile` that Puma will use. -pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +port ENV.fetch("PORT", 3000) # Allow puma to be restarted by `bin/rails restart` command. plugin :tmp_restart + +plugin :litestream + +plugin :solid_queue + +# Only use a pidfile when requested +pidfile ENV["PIDFILE"] if ENV["PIDFILE"] diff --git a/config/solid_cache.yml b/config/solid_cache.yml new file mode 100644 index 0000000..98339f6 --- /dev/null +++ b/config/solid_cache.yml @@ -0,0 +1,15 @@ +default: &default + database: cache + store_options: + max_age: <%= 1.week.to_i %> + max_size: <%= 512.megabytes %> + namespace: <%= Rails.env %> + +development: + <<: *default + +test: + <<: *default + +production: + <<: *default diff --git a/config/solid_queue.yml b/config/solid_queue.yml index 520c70b..bc3f7f3 100644 --- a/config/solid_queue.yml +++ b/config/solid_queue.yml @@ -2,6 +2,11 @@ default: &default dispatchers: - polling_interval: 1 batch_size: 500 + recurring_tasks: + # periodic_litestream_backup_verfication_job: + # class: Litestream::VerificationJob + # args: [] + # schedule: every day at 1am EST workers: - queues: "*" threads: 3 diff --git a/db/cache_migrate/20240512200132_create_solid_cache_entries.solid_cache.rb b/db/cache_migrate/20240512200132_create_solid_cache_entries.solid_cache.rb new file mode 100644 index 0000000..04af347 --- /dev/null +++ b/db/cache_migrate/20240512200132_create_solid_cache_entries.solid_cache.rb @@ -0,0 +1,12 @@ +# This migration comes from solid_cache (originally 20230724121448) +class CreateSolidCacheEntries < ActiveRecord::Migration[7.0] + def change + create_table :solid_cache_entries do |t| + t.binary :key, null: false, limit: 1024 + t.binary :value, null: false, limit: 512.megabytes + t.datetime :created_at, null: false + + t.index :key, unique: true + end + end +end diff --git a/db/cache_migrate/20240512200133_add_key_hash_and_byte_size_to_solid_cache_entries.solid_cache.rb b/db/cache_migrate/20240512200133_add_key_hash_and_byte_size_to_solid_cache_entries.solid_cache.rb new file mode 100644 index 0000000..43fa028 --- /dev/null +++ b/db/cache_migrate/20240512200133_add_key_hash_and_byte_size_to_solid_cache_entries.solid_cache.rb @@ -0,0 +1,9 @@ +# This migration comes from solid_cache (originally 20240108155507) +class AddKeyHashAndByteSizeToSolidCacheEntries < ActiveRecord::Migration[7.0] + def change + change_table :solid_cache_entries do |t| + t.column :key_hash, :integer, null: true, limit: 8 + t.column :byte_size, :integer, null: true, limit: 4 + end + end +end diff --git a/db/cache_migrate/20240512200134_add_key_hash_and_byte_size_indexes_and_null_constraints_to_solid_cache_entries.solid_cache.rb b/db/cache_migrate/20240512200134_add_key_hash_and_byte_size_indexes_and_null_constraints_to_solid_cache_entries.solid_cache.rb new file mode 100644 index 0000000..52c9568 --- /dev/null +++ b/db/cache_migrate/20240512200134_add_key_hash_and_byte_size_indexes_and_null_constraints_to_solid_cache_entries.solid_cache.rb @@ -0,0 +1,12 @@ +# This migration comes from solid_cache (originally 20240110111600) +class AddKeyHashAndByteSizeIndexesAndNullConstraintsToSolidCacheEntries < ActiveRecord::Migration[7.0] + def change + change_table :solid_cache_entries, bulk: true do |t| + t.change_null :key_hash, false + t.change_null :byte_size, false + t.index :key_hash, unique: true + t.index [:key_hash, :byte_size] + t.index :byte_size + end + end +end diff --git a/db/cache_migrate/20240512200135_remove_key_index_from_solid_cache_entries.solid_cache.rb b/db/cache_migrate/20240512200135_remove_key_index_from_solid_cache_entries.solid_cache.rb new file mode 100644 index 0000000..72ee613 --- /dev/null +++ b/db/cache_migrate/20240512200135_remove_key_index_from_solid_cache_entries.solid_cache.rb @@ -0,0 +1,8 @@ +# This migration comes from solid_cache (originally 20240110111702) +class RemoveKeyIndexFromSolidCacheEntries < ActiveRecord::Migration[7.0] + def change + change_table :solid_cache_entries do |t| + t.remove_index :key, unique: true + end + end +end diff --git a/db/cache_schema.rb b/db/cache_schema.rb new file mode 100644 index 0000000..7fa533c --- /dev/null +++ b/db/cache_schema.rb @@ -0,0 +1,24 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.2].define(version: 2024_05_12_200135) do + create_table "solid_cache_entries", force: :cascade do |t| + t.binary "key", limit: 1024, null: false + t.binary "value", limit: 536870912, null: false + t.datetime "created_at", null: false + t.integer "key_hash", limit: 8, null: false + t.integer "byte_size", limit: 4, null: false + t.index ["byte_size"], name: "index_solid_cache_entries_on_byte_size" + t.index ["key_hash", "byte_size"], name: "index_solid_cache_entries_on_key_hash_and_byte_size" + t.index ["key_hash"], name: "index_solid_cache_entries_on_key_hash", unique: true + end +end diff --git a/db/migrate/20240128210010_create_solid_errors_tables.rb b/db/errors_migrate/20240513053645_create_solid_errors_tables.rb similarity index 53% rename from db/migrate/20240128210010_create_solid_errors_tables.rb rename to db/errors_migrate/20240513053645_create_solid_errors_tables.rb index 5719e9c..6568fc4 100644 --- a/db/migrate/20240128210010_create_solid_errors_tables.rb +++ b/db/errors_migrate/20240513053645_create_solid_errors_tables.rb @@ -1,17 +1,16 @@ # frozen_string_literal: true -class CreateSolidErrorsTables < ActiveRecord::Migration[7.1] +class CreateSolidErrorsTables < ActiveRecord::Migration[7.2] def change create_table :solid_errors do |t| - t.string :exception_class, null: false - t.string :message, null: false - t.string :severity, null: false - t.string :source + t.text :exception_class, null: false + t.text :message, null: false + t.text :severity, null: false + t.text :source t.datetime :resolved_at, index: true + t.string :fingerprint, null: false, limit: 64, index: {unique: true} t.timestamps - - t.index [:exception_class, :message, :severity, :source], unique: true, name: "solid_error_uniqueness_index" end create_table :solid_errors_occurrences do |t| diff --git a/db/errors_schema.rb b/db/errors_schema.rb new file mode 100644 index 0000000..60d221e --- /dev/null +++ b/db/errors_schema.rb @@ -0,0 +1,37 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.2].define(version: 2024_05_13_053645) do + create_table "solid_errors", force: :cascade do |t| + t.text "exception_class", null: false + t.text "message", null: false + t.text "severity", null: false + t.text "source" + t.datetime "resolved_at" + t.string "fingerprint", limit: 64, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["fingerprint"], name: "index_solid_errors_on_fingerprint", unique: true + t.index ["resolved_at"], name: "index_solid_errors_on_resolved_at" + end + + create_table "solid_errors_occurrences", force: :cascade do |t| + t.integer "error_id", null: false + t.text "backtrace" + t.json "context" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["error_id"], name: "index_solid_errors_occurrences_on_error_id" + end + + add_foreign_key "solid_errors_occurrences", "solid_errors", column: "error_id" +end diff --git a/db/migrate/20240313184443_create_solid_queue_tables.solid_queue.rb b/db/queue_migrate/20240512201746_create_solid_queue_tables.solid_queue.rb similarity index 100% rename from db/migrate/20240313184443_create_solid_queue_tables.solid_queue.rb rename to db/queue_migrate/20240512201746_create_solid_queue_tables.solid_queue.rb diff --git a/db/migrate/20240313184444_add_missing_index_to_blocked_executions.solid_queue.rb b/db/queue_migrate/20240512201747_add_missing_index_to_blocked_executions.solid_queue.rb similarity index 100% rename from db/migrate/20240313184444_add_missing_index_to_blocked_executions.solid_queue.rb rename to db/queue_migrate/20240512201747_add_missing_index_to_blocked_executions.solid_queue.rb diff --git a/db/queue_migrate/20240513061123_create_recurring_executions.solid_queue.rb b/db/queue_migrate/20240513061123_create_recurring_executions.solid_queue.rb new file mode 100644 index 0000000..7f441b2 --- /dev/null +++ b/db/queue_migrate/20240513061123_create_recurring_executions.solid_queue.rb @@ -0,0 +1,15 @@ +# This migration comes from solid_queue (originally 20240218110712) +class CreateRecurringExecutions < ActiveRecord::Migration[7.1] + def change + create_table :solid_queue_recurring_executions do |t| + t.references :job, index: {unique: true}, null: false + t.string :task_key, null: false + t.datetime :run_at, null: false + t.datetime :created_at, null: false + + t.index [:task_key, :run_at], unique: true + end + + add_foreign_key :solid_queue_recurring_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + end +end diff --git a/db/queue_schema.rb b/db/queue_schema.rb new file mode 100644 index 0000000..3f4979e --- /dev/null +++ b/db/queue_schema.rb @@ -0,0 +1,123 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.2].define(version: 2024_05_13_061123) do + create_table "solid_queue_blocked_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.string "concurrency_key", null: false + t.datetime "expires_at", null: false + t.datetime "created_at", null: false + t.index ["concurrency_key", "priority", "job_id"], name: "index_solid_queue_blocked_executions_for_release" + t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance" + t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true + end + + create_table "solid_queue_claimed_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.bigint "process_id" + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true + t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id" + end + + create_table "solid_queue_failed_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.text "error" + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true + end + + create_table "solid_queue_jobs", force: :cascade do |t| + t.string "queue_name", null: false + t.string "class_name", null: false + t.text "arguments" + t.integer "priority", default: 0, null: false + t.string "active_job_id" + t.datetime "scheduled_at" + t.datetime "finished_at" + t.string "concurrency_key" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id" + t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name" + t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at" + t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering" + t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting" + end + + create_table "solid_queue_pauses", force: :cascade do |t| + t.string "queue_name", null: false + t.datetime "created_at", null: false + t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true + end + + create_table "solid_queue_processes", force: :cascade do |t| + t.string "kind", null: false + t.datetime "last_heartbeat_at", null: false + t.bigint "supervisor_id" + t.integer "pid", null: false + t.string "hostname" + t.text "metadata" + t.datetime "created_at", null: false + t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at" + t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id" + end + + create_table "solid_queue_ready_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true + t.index ["priority", "job_id"], name: "index_solid_queue_poll_all" + t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue" + end + + create_table "solid_queue_recurring_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "task_key", null: false + t.datetime "run_at", null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_recurring_executions_on_job_id", unique: true + t.index ["task_key", "run_at"], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true + end + + create_table "solid_queue_scheduled_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.datetime "scheduled_at", null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true + t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all" + end + + create_table "solid_queue_semaphores", force: :cascade do |t| + t.string "key", null: false + t.integer "value", default: 1, null: false + t.datetime "expires_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at" + t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value" + t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true + end + + add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade +end diff --git a/db/schema.rb b/db/schema.rb index e7ab5b3..45d0606 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -118,121 +118,6 @@ t.index ["user_id"], name: "index_sessions_on_user_id" end - create_table "solid_errors", force: :cascade do |t| - t.string "exception_class", null: false - t.string "message", null: false - t.string "severity", null: false - t.string "source" - t.datetime "resolved_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["exception_class", "message", "severity", "source"], name: "solid_error_uniqueness_index", unique: true - t.index ["resolved_at"], name: "index_solid_errors_on_resolved_at" - end - - create_table "solid_errors_occurrences", force: :cascade do |t| - t.integer "error_id", null: false - t.text "backtrace" - t.json "context" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["error_id"], name: "index_solid_errors_occurrences_on_error_id" - end - - create_table "solid_queue_blocked_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.string "queue_name", null: false - t.integer "priority", default: 0, null: false - t.string "concurrency_key", null: false - t.datetime "expires_at", null: false - t.datetime "created_at", null: false - t.index ["concurrency_key", "priority", "job_id"], name: "index_solid_queue_blocked_executions_for_release" - t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance" - t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true - end - - create_table "solid_queue_claimed_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.bigint "process_id" - t.datetime "created_at", null: false - t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true - t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id" - end - - create_table "solid_queue_failed_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.text "error" - t.datetime "created_at", null: false - t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true - end - - create_table "solid_queue_jobs", force: :cascade do |t| - t.string "queue_name", null: false - t.string "class_name", null: false - t.text "arguments" - t.integer "priority", default: 0, null: false - t.string "active_job_id" - t.datetime "scheduled_at" - t.datetime "finished_at" - t.string "concurrency_key" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id" - t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name" - t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at" - t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering" - t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting" - end - - create_table "solid_queue_pauses", force: :cascade do |t| - t.string "queue_name", null: false - t.datetime "created_at", null: false - t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true - end - - create_table "solid_queue_processes", force: :cascade do |t| - t.string "kind", null: false - t.datetime "last_heartbeat_at", null: false - t.bigint "supervisor_id" - t.integer "pid", null: false - t.string "hostname" - t.text "metadata" - t.datetime "created_at", null: false - t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at" - t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id" - end - - create_table "solid_queue_ready_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.string "queue_name", null: false - t.integer "priority", default: 0, null: false - t.datetime "created_at", null: false - t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true - t.index ["priority", "job_id"], name: "index_solid_queue_poll_all" - t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue" - end - - create_table "solid_queue_scheduled_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.string "queue_name", null: false - t.integer "priority", default: 0, null: false - t.datetime "scheduled_at", null: false - t.datetime "created_at", null: false - t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true - t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all" - end - - create_table "solid_queue_semaphores", force: :cascade do |t| - t.string "key", null: false - t.integer "value", default: 1, null: false - t.datetime "expires_at", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at" - t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value" - t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true - end - create_table "users", force: :cascade do |t| t.string "email", null: false t.string "password_digest", null: false @@ -246,10 +131,4 @@ end add_foreign_key "sessions", "users" - add_foreign_key "solid_errors_occurrences", "solid_errors", column: "error_id" - add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade - add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade - add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade - add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade - add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade end