From f17156a65eccfab7ca131d9850ee7f38ead08476 Mon Sep 17 00:00:00 2001 From: lorenzo farnararo Date: Sat, 17 Aug 2024 17:11:39 +0200 Subject: [PATCH] solid queue and postgres --- .vscode/settings.json | 5 + Dockerfile | 8 +- Dockerfile.development | 45 +++++ Gemfile | 7 +- Gemfile.lock | 59 ++----- bin/boot | 54 ------ bin/start-app | 5 - config/database.yml | 18 +- config/deploy.staging.yml | 4 +- config/deploy.yml | 33 ++-- config/environments/production.rb | 15 +- config/redis.conf | 4 - config/resque-pool.yml | 1 - config/routes.rb | 4 - config/solid_queue.yml | 18 ++ ...9_create_solid_queue_tables.solid_queue.rb | 103 ++++++++++++ ...index_to_blocked_executions.solid_queue.rb | 9 + ...create_recurring_executions.solid_queue.rb | 17 ++ db/schema.rb | 154 +++++++++++++++--- docker-compose.yaml | 31 ++++ 20 files changed, 422 insertions(+), 172 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 Dockerfile.development delete mode 100755 bin/boot delete mode 100755 bin/start-app delete mode 100644 config/redis.conf delete mode 100644 config/resque-pool.yml create mode 100644 config/solid_queue.yml create mode 100644 db/migrate/20240817141539_create_solid_queue_tables.solid_queue.rb create mode 100644 db/migrate/20240817141540_add_missing_index_to_blocked_executions.solid_queue.rb create mode 100644 db/migrate/20240817141541_create_recurring_executions.solid_queue.rb create mode 100644 docker-compose.yaml diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..952565e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "yaml.schemas": { + "https://json.schemastore.org/yamllint.json": "file:///home/baldarn/Projects/open-GAS/config/deploy.yml" + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 74bc6e1..62e2ef1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,13 +13,12 @@ ENV RAILS_ENV="production" \ BUNDLE_PATH="/usr/local/bundle" \ BUNDLE_WITHOUT="development" - # Throw-away build stage to reduce size of final image FROM --platform=$TARGETPLATFORM base as build # Install packages needed to build gems RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y build-essential git libvips pkg-config nodejs + apt-get install --no-install-recommends -y build-essential git libpq-dev libvips pkg-config nodejs # Install application gems COPY Gemfile Gemfile.lock .ruby-version ./ @@ -32,13 +31,12 @@ COPY . . # Precompiling assets for production without requiring secret RAILS_MASTER_KEY RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile - # Final stage for app image FROM base # Install packages needed for deployment RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y curl libjemalloc2 libsqlite3-0 libvips redis nodejs && \ + apt-get install --no-install-recommends -y curl libjemalloc2 libpq-dev libvips nodejs && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives # Copy built artifacts: gems, application @@ -62,4 +60,4 @@ ENTRYPOINT ["/rails/bin/docker-entrypoint"] # Start the server by default, this can be overwritten at runtime EXPOSE 3000 -CMD ["bin/boot"] +CMD ["bin/rails", "s", "-b", "0.0.0.0"] diff --git a/Dockerfile.development b/Dockerfile.development new file mode 100644 index 0000000..2405d8d --- /dev/null +++ b/Dockerfile.development @@ -0,0 +1,45 @@ +# syntax = docker/dockerfile:1 + +# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile +ARG RUBY_VERSION=3.3.4 +FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base + +# Rails app lives here +WORKDIR /rails + +# Set production environment +ENV RAILS_ENV="development" \ + BUNDLE_PATH="/usr/local/bundle" + +# Throw-away build stage to reduce size of final image +FROM --platform=$TARGETPLATFORM base as build + +# Install packages needed to build gems +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y build-essential git libvips libpq-dev pkg-config nodejs + +# Install application gems +COPY Gemfile Gemfile.lock .ruby-version ./ +RUN bundle install && \ + rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git + +# Copy application code +COPY . . + +# Precompiling assets for production without requiring secret RAILS_MASTER_KEY +RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile + +# Final stage for app image +FROM base + +# Install packages needed for deployment +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y curl libjemalloc2 libpq-dev libvips nodejs && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + +# Copy built artifacts: gems, application +COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" +COPY --from=build /rails /rails + +# Entrypoint prepares the application. +ENTRYPOINT ["/rails/bin/docker-entrypoint"] diff --git a/Gemfile b/Gemfile index d70bc1d..4f00abc 100644 --- a/Gemfile +++ b/Gemfile @@ -7,15 +7,13 @@ ruby file: '.ruby-version' gem 'rails', '~> 7.2.0' # Drivers -gem 'redis', '>= 4.0.1' -gem 'sqlite3', '~> 1.4' +gem 'pg', '~> 1.5.7' # Deployment gem 'puma', '>= 5.0' # Jobs -gem 'resque', '~> 2.6.0' -gem 'resque-pool', '~> 0.7.1' +gem 'solid_queue', '~> 0.4.1' # Front-end gem 'bootstrap', '~> 5.1' @@ -43,7 +41,6 @@ gem 'rouge', '~> 4.2' gem 'rqrcode' gem 'sassc-rails' gem 'sprockets-rails' -gem 'thruster' gem 'useragent', github: 'basecamp/useragent' group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index 26b33a3..aea69f3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -129,6 +129,8 @@ GEM drb (2.2.1) ed25519 (1.3.0) erubi (1.13.0) + et-orbi (1.2.11) + tzinfo execjs (2.9.1) faker (3.4.1) i18n (>= 1.8.11, < 2) @@ -139,6 +141,9 @@ GEM ffi (1.17.0-x86_64-darwin) ffi (1.17.0-x86_64-linux-gnu) front_matter_parser (1.0.1) + fugit (1.11.1) + et-orbi (~> 1, >= 1.2.11) + raabro (~> 1.4) globalid (1.2.1) activesupport (>= 6.1) htmlbeautifier (1.4.3) @@ -200,10 +205,6 @@ GEM mini_magick (4.13.0) mini_mime (1.1.5) minitest (5.24.1) - mono_logger (1.1.2) - multi_json (1.15.0) - mustermann (3.0.0) - ruby2_keywords (~> 0.0.1) net-imap (0.4.14) date net-protocol @@ -236,17 +237,16 @@ GEM parser (3.3.3.0) ast (~> 2.4.1) racc + pg (1.5.7) popper_js (2.11.8) psych (5.1.2) stringio public_suffix (5.0.5) puma (6.4.2) nio4r (~> 2.0) + raabro (1.4.0) racc (1.8.1) rack (3.1.7) - rack-protection (4.0.0) - base64 (>= 0.1.0) - rack (>= 3.0.0, < 4) rack-session (2.0.0) rack (>= 3.0.0) rack-test (2.1.0) @@ -291,26 +291,12 @@ GEM rdoc (6.7.0) psych (>= 4.0.0) redcarpet (3.6.0) - redis (5.2.0) - redis-client (>= 0.22.0) - redis-client (0.22.2) - connection_pool - redis-namespace (1.11.0) - redis (>= 4) regexp_parser (2.9.2) reline (0.5.9) io-console (~> 0.5) responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - resque (2.6.0) - mono_logger (~> 1.0) - multi_json (~> 1.0) - redis-namespace (~> 1.6) - sinatra (>= 0.9.2) - resque-pool (0.7.1) - rake (>= 10.0, < 14.0) - resque (>= 1.22, < 3) rexml (3.3.4) strscan rouge (4.3.0) @@ -341,7 +327,6 @@ GEM ruby-progressbar (1.13.0) ruby-vips (2.2.1) ffi (~> 1.12) - ruby2_keywords (0.0.5) rubyzip (2.3.2) sassc (2.4.0) ffi (~> 1.9) @@ -362,12 +347,12 @@ GEM simple_form (5.3.1) actionpack (>= 5.2) activemodel (>= 5.2) - sinatra (4.0.0) - mustermann (~> 3.0) - rack (>= 3.0.0, < 4) - rack-protection (= 4.0.0) - rack-session (>= 2.0.0, < 3) - tilt (~> 2.0) + solid_queue (0.4.1) + activejob (>= 7.1) + activerecord (>= 7.1) + concurrent-ruby (>= 1.3.1) + fugit (~> 1.11.0) + railties (>= 7.1) sprockets (4.2.1) concurrent-ruby (~> 1.0) rack (>= 2.2.4, < 4) @@ -375,12 +360,6 @@ GEM actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - sqlite3 (1.7.3-aarch64-linux) - sqlite3 (1.7.3-arm-linux) - sqlite3 (1.7.3-arm64-darwin) - sqlite3 (1.7.3-x86-linux) - sqlite3 (1.7.3-x86_64-darwin) - sqlite3 (1.7.3-x86_64-linux) sshkit (1.23.0) base64 net-scp (>= 1.1.2) @@ -391,11 +370,6 @@ GEM stringio (3.1.1) strscan (3.1.0) thor (1.3.1) - thruster (0.1.4) - thruster (0.1.4-aarch64-linux) - thruster (0.1.4-arm64-darwin) - thruster (0.1.4-x86_64-darwin) - thruster (0.1.4-x86_64-linux) tilt (2.3.0) timeout (0.4.1) turbo-rails (2.0.5) @@ -447,13 +421,11 @@ DEPENDENCIES kamal kaminari kaminari-i18n + pg (~> 1.5.7) puma (>= 5.0) rails (~> 7.2.0) rails-i18n (~> 7.0.0) redcarpet (~> 3.6) - redis (>= 4.0.1) - resque (~> 2.6.0) - resque-pool (~> 0.7.1) rouge (~> 4.2) rqrcode rubocop-capybara @@ -462,10 +434,9 @@ DEPENDENCIES selenium-webdriver simple_calendar simple_form (~> 5.3) + solid_queue (~> 0.4.1) sprockets-rails - sqlite3 (~> 1.4) stimulus-rails - thruster turbo-rails useragent! web-console diff --git a/bin/boot b/bin/boot deleted file mode 100755 index 5106115..0000000 --- a/bin/boot +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env ruby - -require "json" -require "yaml" - -class ProcessMonitor - SIGNALS = %w[ INT TERM CLD ] - - def initialize(procfile) - @procs = process_list(procfile) - handle_signals - - @procs.each &:start - @procs.each &:wait - end - - private - def process_list(procfile) - config = YAML.load_file(procfile) - config.map { |name, cmd| MonitoredProcess.new(name, cmd) } - end - - def handle_signals - SIGNALS.each do |signal| - Signal.trap(signal) do - @procs.each &:terminate - end - end - end -end - -class MonitoredProcess - def initialize(name, cmd) - @name, @cmd = name, cmd - end - - def start - @pid = Process.spawn(@cmd) - end - - def wait - Process.wait @pid - rescue Errno::ECHILD - nil - end - - def terminate - Process.kill "TERM", @pid - rescue Errno::ESRCH - nil - end -end - -ProcessMonitor.new("Procfile") diff --git a/bin/start-app b/bin/start-app deleted file mode 100755 index 9a751c2..0000000 --- a/bin/start-app +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -e - -rm -f tmp/pids/server.pid -./bin/rails db:prepare -./bin/rails server diff --git a/config/database.yml b/config/database.yml index c9c3f44..a415269 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,20 +1,24 @@ default: &default - adapter: sqlite3 - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 10 } %> - retries: 100 - default_transaction_mode: immediate + adapter: postgresql + pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 10 } %> + host: <%= ENV.fetch('PG_HOST', 'localhost') %> + port: <%= ENV.fetch('PG_PORT', '5432') %> + username: <%= ENV.fetch('PG_USER', 'opengas') %> + password: <%= ENV.fetch('PG_PASSWORD', 'opengas') %> + database: <%= ENV.fetch('PG_DATABASE', "opengas_#{Rails.env}") %> + encoding: unicode development: primary: <<: *default - database: storage/db/development.sqlite3 test: primary: <<: *default - database: storage/db/test.sqlite3 + database: <%= ENV.fetch('PG_DATABASE', 'opengas_test') %> production: primary: <<: *default - database: storage/db/production.sqlite3 + password: <%= ENV.fetch('PG_PRODUCTION_PASSWORD', 'opengas') %> + diff --git a/config/deploy.staging.yml b/config/deploy.staging.yml index 8895e66..e128154 100644 --- a/config/deploy.staging.yml +++ b/config/deploy.staging.yml @@ -5,10 +5,10 @@ image: baldarn/open-gas servers: web: hosts: - - open-gas-dev.farnararo.it + - staging.opengas.eu labels: traefik.http.routers.open_gas.entrypoints: websecure - traefik.http.routers.open_gas.rule: Host(`open-gas-dev.farnararo.it`) + traefik.http.routers.open_gas.rule: Host(`staging.opengas.eu`) traefik.http.routers.open_gas.tls.certresolver: letsencrypt registry: diff --git a/config/deploy.yml b/config/deploy.yml index 06d3776..fcd8d9a 100644 --- a/config/deploy.yml +++ b/config/deploy.yml @@ -8,10 +8,10 @@ image: baldarn/open-gas servers: web: hosts: - - open-gas.farnararo.it + - opengas.eu labels: traefik.http.routers.open_gas.entrypoints: websecure - traefik.http.routers.open_gas.rule: Host(`open-gas.farnararo.it`) + traefik.http.routers.open_gas.rule: Host(`opengas.eu`) traefik.http.routers.open_gas.tls.certresolver: letsencrypt # Credentials for your image host. @@ -29,6 +29,7 @@ registry: env: secret: - RAILS_MASTER_KEY + - POSTGRES_PASSWORD # Use a different ssh user than root # ssh: @@ -45,21 +46,19 @@ env: # host: ssh://app@192.168.0.1 # Use accessory services (secrets come from .env). -# accessories: -# db: -# image: mysql:8.0 -# host: 192.168.0.2 -# port: 3306 -# env: -# clear: -# MYSQL_ROOT_HOST: '%' -# secret: -# - MYSQL_ROOT_PASSWORD -# files: -# - config/mysql/production.cnf:/etc/mysql/my.cnf -# - db/production.sql:/docker-entrypoint-initdb.d/setup.sql -# directories: -# - data:/var/lib/mysql +accessories: + db: + image: postgres:16.4 + host: opengas.eu + port: 5432 + env: + clear: + POSTGRES_DB: "opengas_production" + POSTGRES_USER: "opengas" + secret: + - POSTGRES_PASSWORD + directories: + - data:/var/lib/postgresql/data # redis: # image: redis:7.0 # host: 192.168.0.2 diff --git a/config/environments/production.rb b/config/environments/production.rb index b8ab0cf..9b039ce 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -70,10 +70,10 @@ config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info') # Use a different cache store in production. - config.cache_store = :redis_cache_store + config.cache_store = :memory_store # Use a real queuing backend for Active Job (and separate queues per environment). - # config.active_job.queue_adapter = :resque + config.active_job.queue_adapter = :solid_queue # config.active_job.queue_name_prefix = "open_gas_production" # Disable caching for Action Mailer templates even if Action Controller @@ -84,6 +84,15 @@ # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false + config.action_mailer.smtp_settings = { + address: ENV.fetch('SMTP_ADDRESS', 'smtp'), + port: 587, + user_name: ENV.fetch('SMTP_USERNAME', 'user'), + password: ENV.fetch('SMTP_PASSWORD', 'password'), + authentication: 'plain', + enable_starttls: true + } + # 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 @@ -105,7 +114,7 @@ # SQLite is good, actually config.active_record.sqlite3_production_warning = false - config.active_job.queue_adapter = :resque + config.active_job.queue_adapter = :solid_queue config.assets.manifest = Rails.root.join('config/manifest.json') end diff --git a/config/redis.conf b/config/redis.conf deleted file mode 100644 index 804d865..0000000 --- a/config/redis.conf +++ /dev/null @@ -1,4 +0,0 @@ -port 6379 -daemonize no -appendonly no -save "" diff --git a/config/resque-pool.yml b/config/resque-pool.yml deleted file mode 100644 index 64f569b..0000000 --- a/config/resque-pool.yml +++ /dev/null @@ -1 +0,0 @@ -default: <%= (Concurrent.processor_count * 0.5).ceil %> diff --git a/config/routes.rb b/config/routes.rb index eaac677..ad6d171 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'resque/server' - Rails.application.routes.draw do root to: 'home#index' @@ -29,7 +27,5 @@ end end - mount Resque::Server.new, at: '/resque' - get 'up' => 'rails/health#show', as: :rails_health_check end diff --git a/config/solid_queue.yml b/config/solid_queue.yml new file mode 100644 index 0000000..26a0d75 --- /dev/null +++ b/config/solid_queue.yml @@ -0,0 +1,18 @@ +default: &default + dispatchers: + - polling_interval: 1 + batch_size: 500 + workers: + - queues: "*" + threads: 3 + processes: 1 + polling_interval: 0.1 + +development: + <<: *default + +test: + <<: *default + +production: + <<: *default diff --git a/db/migrate/20240817141539_create_solid_queue_tables.solid_queue.rb b/db/migrate/20240817141539_create_solid_queue_tables.solid_queue.rb new file mode 100644 index 0000000..9edfc57 --- /dev/null +++ b/db/migrate/20240817141539_create_solid_queue_tables.solid_queue.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +# This migration comes from solid_queue (originally 20231211200639) +class CreateSolidQueueTables < ActiveRecord::Migration[7.0] + def change + create_table :solid_queue_jobs do |t| + t.string :queue_name, null: false + t.string :class_name, null: false, index: true + t.text :arguments + t.integer :priority, default: 0, null: false + t.string :active_job_id, index: true + t.datetime :scheduled_at + t.datetime :finished_at, index: true + t.string :concurrency_key + + t.timestamps + + t.index %i[queue_name finished_at], name: 'index_solid_queue_jobs_for_filtering' + t.index %i[scheduled_at finished_at], name: 'index_solid_queue_jobs_for_alerting' + end + + create_table :solid_queue_scheduled_executions do |t| + t.references :job, index: { unique: true }, 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 %i[scheduled_at priority job_id], name: 'index_solid_queue_dispatch_all' + end + + create_table :solid_queue_ready_executions do |t| + t.references :job, index: { unique: true }, null: false + t.string :queue_name, null: false + t.integer :priority, default: 0, null: false + + t.datetime :created_at, null: false + + t.index %i[priority job_id], name: 'index_solid_queue_poll_all' + t.index %i[queue_name priority job_id], name: 'index_solid_queue_poll_by_queue' + end + + create_table :solid_queue_claimed_executions do |t| + t.references :job, index: { unique: true }, null: false + t.bigint :process_id + t.datetime :created_at, null: false + + t.index %i[process_id job_id] + end + + create_table :solid_queue_blocked_executions do |t| + t.references :job, index: { unique: true }, 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 %i[expires_at concurrency_key], name: 'index_solid_queue_blocked_executions_for_maintenance' + end + + create_table :solid_queue_failed_executions do |t| + t.references :job, index: { unique: true }, null: false + t.text :error + t.datetime :created_at, null: false + end + + create_table :solid_queue_pauses do |t| + t.string :queue_name, null: false, index: { unique: true } + t.datetime :created_at, null: false + end + + create_table :solid_queue_processes do |t| + t.string :kind, null: false + t.datetime :last_heartbeat_at, null: false, index: true + t.bigint :supervisor_id, index: true + + t.integer :pid, null: false + t.string :hostname + t.text :metadata + + t.datetime :created_at, null: false + end + + create_table :solid_queue_semaphores do |t| + t.string :key, null: false, index: { unique: true } + t.integer :value, default: 1, null: false + t.datetime :expires_at, null: false, index: true + + t.timestamps + + t.index %i[key value], name: 'index_solid_queue_semaphores_on_key_and_value' + 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_scheduled_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + end +end diff --git a/db/migrate/20240817141540_add_missing_index_to_blocked_executions.solid_queue.rb b/db/migrate/20240817141540_add_missing_index_to_blocked_executions.solid_queue.rb new file mode 100644 index 0000000..b4fffb5 --- /dev/null +++ b/db/migrate/20240817141540_add_missing_index_to_blocked_executions.solid_queue.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# This migration comes from solid_queue (originally 20240110143450) +class AddMissingIndexToBlockedExecutions < ActiveRecord::Migration[7.1] + def change + add_index :solid_queue_blocked_executions, %i[concurrency_key priority job_id], + name: 'index_solid_queue_blocked_executions_for_release' + end +end diff --git a/db/migrate/20240817141541_create_recurring_executions.solid_queue.rb b/db/migrate/20240817141541_create_recurring_executions.solid_queue.rb new file mode 100644 index 0000000..6dd45dd --- /dev/null +++ b/db/migrate/20240817141541_create_recurring_executions.solid_queue.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +# 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 %i[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/schema.rb b/db/schema.rb index e222eef..8780392 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,10 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_08_12_135310) do +ActiveRecord::Schema[7.2].define(version: 2024_08_17_141541) do + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -47,8 +50,8 @@ end create_table "event_groups", force: :cascade do |t| - t.integer "event_id" - t.integer "group_id" + t.bigint "event_id" + t.bigint "group_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["event_id"], name: "index_event_groups_on_event_id" @@ -56,7 +59,7 @@ end create_table "events", force: :cascade do |t| - t.integer "club_id" + t.bigint "club_id" t.string "title", null: false t.integer "kind", null: false t.date "date_from", null: false @@ -65,7 +68,7 @@ t.time "time_to" t.boolean "all_day", default: false, null: false t.text "description" - t.integer "place_id" + t.bigint "place_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["club_id"], name: "index_events_on_club_id" @@ -73,7 +76,7 @@ end create_table "expense_reasons", force: :cascade do |t| - t.integer "club_id" + t.bigint "club_id" t.string "reason", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -81,8 +84,8 @@ end create_table "expenses", force: :cascade do |t| - t.integer "club_id" - t.integer "expense_reason_id" + t.bigint "club_id" + t.bigint "expense_reason_id" t.integer "amount", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -91,7 +94,7 @@ end create_table "groups", force: :cascade do |t| - t.integer "club_id" + t.bigint "club_id" t.string "name", null: false t.integer "default_amount" t.datetime "created_at", null: false @@ -100,8 +103,8 @@ end create_table "member_groups", force: :cascade do |t| - t.integer "member_id" - t.integer "group_id" + t.bigint "member_id" + t.bigint "group_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["group_id"], name: "index_member_groups_on_group_id" @@ -109,8 +112,8 @@ end create_table "member_tags", force: :cascade do |t| - t.integer "member_id" - t.integer "tag_id" + t.bigint "member_id" + t.bigint "tag_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["member_id"], name: "index_member_tags_on_member_id" @@ -118,7 +121,7 @@ end create_table "members", force: :cascade do |t| - t.integer "club_id" + t.bigint "club_id" t.string "first_name", null: false t.string "last_name", null: false t.date "born_at", null: false @@ -144,7 +147,7 @@ end create_table "payment_reasons", force: :cascade do |t| - t.integer "club_id" + t.bigint "club_id" t.string "reason", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -152,8 +155,8 @@ end create_table "payments", force: :cascade do |t| - t.integer "member_id" - t.integer "payment_reason_id" + t.bigint "member_id" + t.bigint "payment_reason_id" t.integer "amount", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -168,8 +171,8 @@ end create_table "presences", force: :cascade do |t| - t.integer "member_id" - t.integer "event_id" + t.bigint "member_id" + t.bigint "event_id" t.date "date", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -177,8 +180,111 @@ t.index ["member_id"], name: "index_presences_on_member_id" end + create_table "solid_queue_blocked_executions", force: :cascade do |t| + t.bigint "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.bigint "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.bigint "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.bigint "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.bigint "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.bigint "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 "tags", force: :cascade do |t| - t.integer "club_id" + t.bigint "club_id" t.string "name", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -186,7 +292,7 @@ end create_table "users", force: :cascade do |t| - t.integer "club_id" + t.bigint "club_id" t.string "first_name", null: false t.string "last_name", null: false t.date "blsd_expires_at" @@ -214,4 +320,10 @@ add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_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_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/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..cba3ba8 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,31 @@ +volumes: + db_storage: + +services: + db: + image: postgres:16.4 + restart: unless-stopped + volumes: + - db_storage:/var/lib/postgresql/data + ports: + - ${PG_PORT}:5432 + environment: + - POSTGRES_USER=opengas + - POSTGRES_PASSWORD=opengas + + solid_queue: + restart: unless-stopped + build: + context: . + dockerfile: Dockerfile.development + ssh: + - default + command: ./bin/rake solid_queue:start + environment: + - PG_HOST=db + - PGUSER=opengas + - PGPASSWORD=opengas + - PGDATABASE=opengas_development + depends_on: + - db +