Skip to content

Commit bc218e4

Browse files
committed
Migrate to Solid Queue 0.8.x and extract tables
With Solid Queue 0.8.0, support for dedicated databases were introduced. In fact, Rails recommends moving the database, which we perform with the migration. Unfortunately, it is currently unclear how exactly schema migrations will be provided. Therefore, we cannot use the same GitHub actions workflow for now and will re-add it once a new migration has been published.
1 parent 72ee3d6 commit bc218e4

15 files changed

Lines changed: 388 additions & 164 deletions

.github/workflows/ci.yml

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,10 @@ jobs:
6666
cp config/database.yml.ci config/database.yml
6767
cp config/mnemosyne.yml.ci config/mnemosyne.yml
6868
69-
- name: Create database
69+
- name: Prepare database
7070
env:
7171
RAILS_ENV: test
72-
run: bundler exec rake db:schema:load
73-
- name: Temporarily create pending SolidQueue migrations
74-
# Dependabot might update the SolidQueue gem, which might include new migrations.
75-
# However, Dependabot won't add the migrations nor run SolidQueue at all.
76-
# Consequently, all tests would still pass and the dependency update would be merged.
77-
# To prevent this, we temporarily create the pending migrations *after* the schema has been loaded.
78-
# If a new migration was added, a `PendingMigrationError` will be raised and the CI will fail.
79-
env:
80-
RAILS_ENV: test
81-
run: bundler exec rails solid_queue:install:migrations
72+
run: bundler exec rake db:prepare
8273
- name: Precompile assets
8374
env:
8475
RAILS_ENV: test

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ AllCops:
2323
NewCops: enable
2424
Exclude:
2525
- 'bin/*'
26-
- 'db/schema.rb'
26+
- 'db/*schema.rb'
2727
- 'vendor/**/*'
2828
# Ignore local files for faster processing
2929
- 'tmp/**/*'

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ GEM
528528
rexml (~> 3.2)
529529
rubocop (>= 1.0, < 2.0)
530530
slim (>= 3.0, < 6.0)
531-
solid_queue (0.7.1)
531+
solid_queue (0.8.2)
532532
activejob (>= 7.1)
533533
activerecord (>= 7.1)
534534
concurrent-ruby (>= 1.3.1)

config/database.yml.example

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ default: &default
2929
<% end %>
3030

3131
development:
32-
<<: *default
33-
database: codeharbor_development
32+
primary: &primary_development
33+
<<: *default
34+
database: codeharbor_development
35+
queue:
36+
<<: *primary_development
37+
database: codeharbor_development_queue
38+
migrations_paths: db/queue_migrate
3439

3540
# Warning: The database defined as "test" will be erased and
3641
# re-generated from your development database when you run "rake".
@@ -56,5 +61,10 @@ test:
5661
# for a full overview on how database connection configuration can be specified.
5762
#
5863
production:
59-
<<: *default
60-
database: codeharbor_production
64+
primary: &primary_production
65+
<<: *default
66+
database: codeharbor_production
67+
queue:
68+
<<: *primary_production
69+
database: codeharbor_production_queue
70+
migrations_paths: db/queue_migrate

config/environments/development.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353

5454
# Use a real queuing backend for Active Job (and separate queues per environment).
5555
config.active_job.queue_adapter = :solid_queue
56+
config.solid_queue.connects_to = {database: {writing: :queue}}
5657
config.active_job.queue_name_prefix = 'codeharbor_development'
5758

5859
# Disable caching for Action Mailer templates even if Action Controller

config/environments/production.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686

8787
# Use a real queuing backend for Active Job (and separate queues per environment).
8888
config.active_job.queue_adapter = :solid_queue
89+
config.solid_queue.connects_to = {database: {writing: :queue}}
8990
config.active_job.queue_name_prefix = 'codeharbor_production'
9091

9192
# Disable caching for Action Mailer templates even if Action Controller

config/solid_queue.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
default: &default
2-
dispatchers:
3-
- polling_interval: 1
4-
batch_size: 500
5-
workers:
6-
- queues: "*"
7-
threads: 3
8-
processes: 1
9-
polling_interval: 0.1
1+
default: &default
2+
dispatchers:
3+
- polling_interval: 1
4+
batch_size: 500
5+
workers:
6+
- queues: "*"
7+
threads: 3
8+
processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
9+
polling_interval: 0.1
1010

11-
development:
11+
development:
1212
<<: *default
1313

14-
test:
14+
test:
1515
<<: *default
1616

17-
production:
17+
production:
1818
<<: *default
1919
dispatchers:
2020
- polling_interval: 1
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# frozen_string_literal: true
2+
3+
require_relative '../scripts/copy_data'
4+
5+
class MoveSolidQueueToDedicatedDatabase < ActiveRecord::Migration[7.1]
6+
include CopyData
7+
include ActiveRecord::Tasks
8+
9+
class Queue < ApplicationRecord
10+
self.abstract_class = true
11+
connects_to database: {writing: :queue}
12+
end
13+
14+
def up
15+
create_database(:queue)
16+
load_queue_schema(database: :queue)
17+
copy_data(source_connection: connection, target_connection: Queue.connection, operation: :matches, condition: 'solid_queue_%')
18+
drop_queue_tables(connection:)
19+
ensure
20+
Queue.connection&.disconnect!
21+
end
22+
23+
def down
24+
load_queue_schema(database: :primary)
25+
copy_data(source_connection: Queue.connection, target_connection: connection, operation: :matches, condition: 'solid_queue_%')
26+
drop_queue_tables(connection: Queue.connection)
27+
rescue StandardError
28+
Queue.connection&.disconnect!
29+
else
30+
Queue.connection&.disconnect!
31+
drop_database(:queue)
32+
end
33+
34+
def foreign_key_targets
35+
%w[
36+
solid_queue_jobs
37+
]
38+
end
39+
40+
private
41+
42+
def load_queue_schema(database:)
43+
with_connection(database:) do
44+
DatabaseTasks.load_schema(configs_for(:queue), ActiveRecord.schema_format, 'db/queue_schema.rb')
45+
end
46+
end
47+
48+
def drop_queue_tables(connection:)
49+
connection.drop_table :solid_queue_semaphores
50+
connection.drop_table :solid_queue_scheduled_executions
51+
connection.drop_table :solid_queue_recurring_tasks
52+
connection.drop_table :solid_queue_recurring_executions
53+
connection.drop_table :solid_queue_ready_executions
54+
connection.drop_table :solid_queue_processes
55+
connection.drop_table :solid_queue_pauses
56+
connection.drop_table :solid_queue_failed_executions
57+
connection.drop_table :solid_queue_claimed_executions
58+
connection.drop_table :solid_queue_blocked_executions
59+
connection.drop_table :solid_queue_jobs
60+
end
61+
62+
def configs_for(name)
63+
ActiveRecord::Base.configurations.configs_for(name: name.to_s, env_name: Rails.env)
64+
end
65+
66+
def create_database(name)
67+
database_name = configs_for(name).database
68+
new_primary_connection.create_database(database_name)
69+
rescue ActiveRecord::DatabaseAlreadyExists
70+
# Database already exists, do nothing
71+
end
72+
73+
def drop_database(name)
74+
database_name = configs_for(name).database
75+
new_primary_connection.drop_database(database_name)
76+
end
77+
78+
def new_primary_connection
79+
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.new(configs_for(:primary).configuration_hash)
80+
end
81+
82+
def with_connection(database:)
83+
# We must not overwrite the `connection`, which is automatically overwritten by establishing a new connection.
84+
# However, we need to specify another connection, i.e. for loading the schema to the desired database.
85+
# Hence, we use this monkey patching workaround to change the connection temporary and then revert back.
86+
klass = database == :queue ? Queue : ApplicationRecord
87+
DatabaseTasks.alias_method :previous_migration_class, :migration_class
88+
DatabaseTasks.define_method(:migration_class) { klass }
89+
yield
90+
ensure
91+
DatabaseTasks.alias_method :migration_class, :previous_migration_class
92+
end
93+
end

db/queue_schema.rb

Lines changed: 144 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)