Understanding the 3 Solids in Rails 8: SolidQueue, SolidCache, and SolidCable Explained

Explore the three essential components of Rails 8: SolidQueue for background jobs, SolidCache for caching, and SolidCable for WebSockets communication

Ruby on Rails 8 introduces three powerful tools for enhancing the performance and scalability of modern web applications: SolidQueue, SolidCache, and SolidCable.

These components—part of the "SOLID" family in Rails 8—focus on key areas such as background job processing, caching, and real-time WebSocket communication.

In this article, we'll dive into each of these, explain how they work, and provide code examples that leverage Rails' Hotwire framework for real-time updates.

1. SolidQueue: Efficient Database-Backed Job Processing

SolidQueue in Rails 8 is a database-backed queuing backend for ActiveJob, designed to manage background jobs directly in your SQL database, eliminating the need for external services like Redis or Sidekiq.

By leveraging the existing database infrastructure (MySQL, PostgreSQL, or SQLite), SolidQueue simplifies job management and reduces the complexity and costs associated with third-party services.

Key Features:

  • Database-backed queuing: Jobs are stored and managed within the application's SQL database.

  • No external services required: Removes the need for Redis, Sidekiq, or Resque.

  • Job prioritization and retries: Supports features like job retries, priorities, and scheduling.

  • Simplified deployment: Reduces the overhead and complexity of managing additional queuing services.

Example of Using SolidQueue

Here's how to set up and use SolidQueue in a Rails 8 application:

Step 1: Define a Job

Jobs in SolidQueue are created using ActiveJob. Here's an example of a job to send welcome emails:

# app/jobs/send_email_job.rb
class SendEmailJob < ApplicationJob
  queue_as :default

  def perform(user)
    UserMailer.welcome_email(user).deliver_now
  end
end

Step 2: Enqueue a Job

To enqueue a job, use the perform_later method:

user = User.find(params[:id])
SendEmailJob.perform_later(user)

This queues the job in your database. SolidQueue handles the job processing directly in the SQL database, eliminating the need for external job processing systems.

Step 3: Monitor Jobs

To process jobs, run the Rails job worker, which will handle the queued jobs stored in the database:

$ rails jobs:work

This command starts the job worker that processes the jobs stored in your SQL database, making it simple and efficient to manage background tasks without additional services.


2. SolidCache: Redis-Free Caching Mechanism

SolidCache in Rails 8 offers a robust caching mechanism that removes the need for Redis-based caching solutions.

SolidCache is designed to leverage the application's existing database infrastructure to handle caching, simplifying deployment and reducing costs associated with external caching services like Redis.

Key Features:

  • Redis-free caching: SolidCache eliminates the need for Redis, relying on your existing SQL database for caching.

  • Supports multiple backends: While it doesn't require Redis, it still supports various caching backends like in-memory storage and file storage.

  • Cache fragments, actions, and queries: SolidCache supports all traditional Rails caching techniques, including fragment and action caching.

  • Lower infrastructure complexity: By using your database, SolidCache reduces the need for extra caching services and simplifies your architecture.

Example of Using SolidCache

Here’s how you can cache query results without Redis:

Step 1: Cache a Query

In the controller, you can cache database query results using SolidCache, and the data will be stored in your SQL database instead of Redis:

# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Rails.cache.fetch("all_posts", expires_in: 6.hours) do
      Post.all.to_a
    end
  end
end

In this example, SolidCache caches the result of the Post.all query in your SQL database and serves it from the cache for the next 6 hours, eliminating the need for Redis.

Step 2: Cache View Fragments

You can also cache view fragments to avoid rendering frequently reused components from scratch:

<% cache "recent_posts", expires_in: 6.hours do %>
  <%= render partial: "posts/post", collection: @recent_posts %>
<% end %>

This caches the recent_posts partial for 6 hours, significantly improving performance.

Step 3: Expire Cache

You can manually expire the cache when the underlying data changes:

Rails.cache.delete("all_posts")

This ensures that the cache is cleared when new data is added to the system, allowing for updated content in future requests.


3. SolidCable: Redis-Free Real-Time WebSocket Communication

SolidCable builds upon Rails' ActionCable to enhance real-time WebSocket communication in Rails 8, allowing developers to manage WebSocket connections efficiently without the need for Redis.

Traditionally, Redis was used to handle message broadcasting for WebSockets, but SolidCable replaces this with a more efficient, Redis-free solution that simplifies real-time feature deployment.

With Hotwire, Rails' integrated framework for building real-time features without writing JavaScript, you can easily implement live updates and WebSocket-based interactions in your application.

Key Features:

  • Redis-free WebSocket management: SolidCable eliminates the need for Redis when managing WebSocket connections.

  • Hotwire integration: SolidCable seamlessly works with Hotwire (Turbo and Stimulus) for real-time updates without JavaScript.

  • Multiple backends: SolidCable supports using SQL databases to handle WebSocket connections.

  • High scalability: Suitable for applications requiring large-scale real-time communication, even without Redis.

Example of Using SolidCable with Hotwire

Let’s implement a real-time notification system using SolidCable and Hotwire:

Step 1: Create a Channel

Generate a notification channel:

$ rails generate channel Notification

This creates a notification_channel.rb file. Update it to broadcast messages when needed:

# app/channels/notification_channel.rb
class NotificationChannel < ApplicationCable::Channel
  def subscribed
    stream_from "notifications_#{params[:user_id]}"
  end

  def notify(data)
    ActionCable.server.broadcast "notifications_#{params[:user_id]}", message: data['message']
  end
end

Step 2: Create Hotwire View for Notifications

Using Turbo Streams, we can handle the real-time updates without writing JavaScript. Here’s how to set up a view that updates when a new notification arrives:

<!-- app/views/notifications/index.html.erb -->
<h1>Notifications</h1>

<%= turbo_stream_from "notifications_#{current_user.id}" %>

<div id="notifications">
  <%= render partial: "notification", collection: @notifications %>
</div>

This code establishes a WebSocket connection using Turbo Streams, which will automatically update the notifications section in real-time without any client-side JavaScript.

Step 3: Broadcast Notifications

On the server side, you can broadcast notifications using SolidCable as follows:

# app/controllers/notifications_controller.rb
class NotificationsController < ApplicationController
  def create
    @notification = Notification.create(message: params[:message], user: current_user)
    ActionCable.server.broadcast "notifications_#{current_user.id}", message: @notification.message
    head :ok
  end
end

This setup allows you to broadcast notifications to the relevant users, and the Hotwire framework will automatically update the view with the new notification.


FAQ: SolidQueue, SolidCache, and SolidCable in Rails 8

Q1: What is the difference between SolidQueue and ActiveJob?

A1: SolidQueue is a database-backed queuing backend for ActiveJob. While ActiveJob provides the framework for background job processing, SolidQueue manages these jobs directly within your SQL database (MySQL, PostgreSQL, or SQLite). It eliminates the need for external services like Redis or Sidekiq.

Q2: Can I still use Sidekiq or Resque with SolidQueue?

A2: While SolidQueue manages jobs in the database, you can still configure ActiveJob to use Sidekiq, Resque, or other backends. However, SolidQueue offers a simpler, built-in solution that eliminates the need for these external services.

Q3: How does SolidQueue simplify deployment?

A3: SolidQueue simplifies deployment by using your existing database for job management, eliminating the need to set up and manage external queuing services like Redis or Sidekiq. This reduces the complexity and overhead in your infrastructure.

Q4: How does SolidCache differ from traditional caching solutions?

A4: SolidCache removes the dependency on Redis for caching by leveraging your existing database infrastructure. While Redis is often used in traditional Rails setups, SolidCache offers a robust alternative that reduces the need for additional services, simplifying caching for Rails 8 applications.

Q5: How does SolidCable improve real-time features without Redis?

A5: SolidCable allows developers to manage WebSocket connections and real-time communication without Redis. It leverages existing database infrastructure for message broadcasting, simplifying the setup of real-time features such as live notifications and chat systems, while maintaining scalability.

Q6: Do I need to configure anything special to use SolidQueue, SolidCache, or SolidCable in Rails8?

A6: Rails 8 integrates SolidQueue, SolidCache, and SolidCable by default, requiring minimal configuration. However, depending on your application’s needs, you may need to customize specific settings, such as the cache store configuration or WebSocket backends.

Q7: Are there any performance implications of using SolidQueue over traditional background job processors like Sidekiq?

A7: While SolidQueue provides a straightforward and integrated solution for job processing, its performance may vary depending on your application's workload and database capabilities. For high-throughput scenarios, traditional background processors like Sidekiq may offer better performance, particularly for jobs requiring significant processing power or concurrency. However, SolidQueue simplifies architecture by eliminating the need for additional services.

Q8: How can I monitor job processing and caching performance with SolidQueue and SolidCache?

A8: Rails provides built-in tools for monitoring job processing and caching performance. You can use Rails logs to track job execution times and caching hits/misses. Additionally, third-party monitoring tools like New Relic or Scout can be integrated to provide more advanced insights and metrics regarding job processing and cache performance.

Q9: Can I configure SolidCache to use different caching strategies based on my application needs?

A9: Yes, SolidCache allows you to configure different caching strategies based on your application's requirements. You can set up different cache stores, such as memory stores, file stores, or custom backends, and specify which strategy to use for specific data types or parts of your application.

Q10: How does SolidCable handle message ordering and reliability for real-time updates?

A10: SolidCable ensures that messages are delivered in the order they are sent, as long as the WebSocket connection remains open. For reliability, it's important to implement error handling in your application to manage cases where clients might disconnect or fail to receive messages. You can also implement a reconnection strategy to maintain user experience during connectivity issues.