Run the Solid Trifecta in a Single Database
Hosting on Render or Heroku and need a better solution to just deleting them?
So you want to host your Rails project on Heroku, Render, Digital Ocean. Ran into a Database issue when it came to Solid Cache, Solid Queue, and Solid Cable. I know, me too. Many of us just rip those out of the database.yml
to get it running and forget about it. Works until you need them, but if you are just building small apps and sites, when will you need them. Not to mention, ripping a hole in your app is never a good thing.
I found a better way and would like to share it with you. There are 8 simple steps to complete and you can keep the Solid Trifecta. Leaving the app wired the way Rails intended, just a slimmer version.
First thing is let's take a look at the structure. If you review the `database.yml` you will find the issue at the bottom, included in the production database section.
production:
primary: &primary_production
<<: *default
database: appName_production
username: appName
password: <%= ENV["APP_NAME_DATABASE_PASSWORD"] %>
cache:
<<: *primary_production
database: appName_production_cache
migrations_paths: db/cache_migrate
queue:
<<: *primary_production
database: appName_production_queue
migrations_paths: db/queue_migrate
cable:
<<: *primary_production
database: appName_production_cable
migrations_paths: db/cable_migrate
For production we need 4 databases? You may not even need these services, so why would I spin up other individual databases for them? Let's take a look at the schema's. Take a look in the db folder and you will find the migrate
folder, cable_schema
, cache_schema
, queue_schema
, schema.rb
, and seeds.rb
. Or something similar. Point is to review the trifecta. What you need to do is create a migration for each one. Copy the contents of it's specific schema into the new migration, delete the original and run the new migration. This will migrate the individual schema's into your single, "primary" database as tables. From there we need to do some configuration to point to the single database. If that was confusing, let's break it down step by step.
Steps 1 - 4
Let's create a cable migration.
bin/rails g migration solid_cable
Now lets move the schema config from the cable_schema.rb
into the new solid_cable migration
you just created.
class SolidCable < ActiveRecord::Migration[8.0]
create_table "solid_cable_messages", force: :cascade do |t|
t.binary "channel", limit: 1024, null: false
t.binary "payload", limit: 536870912, null: false
t.datetime "created_at", null: false
t.integer "channel_hash", limit: 8, null: false
t.index [ "channel" ], name: "index_solid_cable_messages_on_channel"
t.index [ "channel_hash" ], name: "index_solid_cable_messages_on_channel_hash"
t.index [ "created_at" ], name: "index_solid_cable_messages_on_created_at"
end
end
Now if you run bin/rails db:migrate
you have moved that one to the working database. I would hold off on running that just yet and go ahead and do the other two. You will do them in exactly the same way. The solid_queue
will be a long one, so I will not put it here. The process is the same for the other two. Rinse and repeat. After you have all three then migrate, but you do you boo.
Step 5
Once you have completed that, steps 1 through 4 are done! Now you need to update the database.yml
. You have moved those schema's to your working database and you have deleted the individual schema's for them in the db
folder. Now you can do what you were originally going to do, and delete those last three databases from production
in the database.yml
. Delete cache
, queue
, and cable
.
Step 6
Now we need to re-configure these. In the config
folder you will find the cable.yml
file. On review you will see that in production it writes to cable
. That is the old database you just deleted. Change that to primary
, pointing to the working database for production. You will also need to change the same in the cache.yml
so that in production it points to primary
Step 7
In the config/environments/production.rb
search for config.solid_queue.connects_to = { database: { writing: :queue } }
and delete this line. It is no longer needed.
Step 8
In the config/environments/development.rb
, add or change the config.active_job.queue_adapter =
to :solid_queue
. By default it is :inline
.
And with that you are done. Review and push, grab a coffee, let the boss know this will take a hot second. Enjoy!
I will drop a note on how to test this set up using a sweet gem called Mission Control from Rails.