Skip to content

Commit

Permalink
Add Channel model to track subscribers
Browse files Browse the repository at this point in the history
  • Loading branch information
npezza93 committed Oct 11, 2024
1 parent 7ac9841 commit 6135781
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 13 deletions.
15 changes: 15 additions & 0 deletions app/models/solid_cable/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module SolidCable
class Channel < SolidCable::Record
scope :for, ->(channel) { where(channel_hash: channel_hash_for(channel)) }

def increment_subscribers!
update!(subscribers: subscribers + 1)
end

def decrement_subscribers!
update!(subscribers: [ subscribers - 1, 0 ].max)
end
end
end
17 changes: 17 additions & 0 deletions app/models/solid_cable/channel_hash.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

module ChannelHash
extend ActiveSupport::Concern

class_methods do
def channel_hashes_for(channels)
channels.map { |channel| channel_hash_for(channel) }
end

# Need to unpack this as a signed integer since Postgresql and SQLite
# don't support unsigned integers
def channel_hash_for(channel)
Digest::SHA256.digest(channel.to_s).unpack1("q>")
end
end
end
13 changes: 4 additions & 9 deletions app/models/solid_cable/message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

module SolidCable
class Message < SolidCable::Record
has_one :channel_record, class_name: "::SolidCable::Channel",
foreign_key: :channel_hash, primary_key: :channel_hash

scope :trimmable, lambda {
where(created_at: ...::SolidCable.message_retention.ago)
}
Expand All @@ -14,16 +17,8 @@ class << self
def broadcast(channel, payload)
insert({ created_at: Time.current, channel:, payload:,
channel_hash: channel_hash_for(channel) })
end

def channel_hashes_for(channels)
channels.map { |channel| channel_hash_for(channel) }
end

# Need to unpack this as a signed integer since Postgresql and SQLite
# don't support unsigned integers
def channel_hash_for(channel)
Digest::SHA256.digest(channel.to_s).unpack1("q>")
channel_record&.subscribers.to_i
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions app/models/solid_cable/record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

module SolidCable
class Record < ActiveRecord::Base
include ChannelHash

self.abstract_class = true

connects_to(**SolidCable.connects_to) if SolidCable.connects_to.present?
Expand Down
8 changes: 5 additions & 3 deletions lib/action_cable/subscription_adapter/solid_cable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ def initialize(*)
end

def broadcast(channel, payload)
::SolidCable::Message.broadcast(channel, payload)

::SolidCable::TrimJob.perform_now if ::SolidCable.autotrim?
::SolidCable::Message.broadcast(channel, payload).tap do
::SolidCable::TrimJob.perform_now if ::SolidCable.autotrim?
end
end

def subscribe(channel, callback, success_callback = nil)
Expand Down Expand Up @@ -64,11 +64,13 @@ def shutdown

def add_channel(channel, on_success)
channels.add(channel)
::SolidCable::Channel.for(channel).first_or_create.increment_subscribers!
event_loop.post(&on_success) if on_success
end

def remove_channel(channel)
channels.delete(channel)
::SolidCable::Channel.for(channel).first_or_create.decrement_subscribers!
end

def invoke_callback(*)
Expand Down
5 changes: 5 additions & 0 deletions lib/generators/solid_cable/add_channels/USAGE
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Description:
Adds Solid Cable channel migration

Example:
bin/rails generate solid_cable:add_channels
15 changes: 15 additions & 0 deletions lib/generators/solid_cable/add_channels/add_channels_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require "rails/generators"
require "rails/generators/active_record"

class SolidCable::AddChannelsGenerator < Rails::Generators::Base
include ActiveRecord::Generators::Migration

source_root File.expand_path("templates", __dir__)

def copy_files
migration_template "db/migrate/create_channels.rb",
"db/cable_migrate/create_channels.rb"
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

class CreateChannels < ActiveRecord::Migration[7.2]
def change
create_table "solid_cable_channels", force: :cascade do |t|
t.integer "channel_hash", limit: 8, null: false
t.integer "subscribers", default: 0, null: false
t.datetime "created_at", null: false
t.index ["channel_hash"], name: "index_solid_cable_channels_on_channel_hash"
end
end
end
4 changes: 4 additions & 0 deletions lib/tasks/solid_cable_tasks.rake
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ namespace :solid_cable do
task :update do
Rails::Command.invoke :generate, [ "solid_cable:update" ]
end

task :add_channels do
Rails::Command.invoke :generate, [ "solid_cable:add_channels" ]
end
end
9 changes: 8 additions & 1 deletion test/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.2].define(version: 2024_09_12_130854) do
ActiveRecord::Schema[7.2].define(version: 2024_10_11_202426) do
create_table "solid_cable_messages", force: :cascade do |t|
t.binary "channel", limit: 1024, null: false
t.binary "payload", limit: 536870912, null: false
Expand All @@ -20,4 +20,11 @@
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

create_table "solid_cable_channels", force: :cascade do |t|
t.integer "channel_hash", limit: 8, null: false
t.integer "subscribers", default: 0, null: false
t.datetime "created_at", null: false
t.index ["channel_hash"], name: "index_solid_cable_channels_on_channel_hash"
end
end
Binary file removed test/dummy/solid_cable_test-shm
Binary file not shown.
Empty file removed test/dummy/solid_cable_test-wal
Empty file.

0 comments on commit 6135781

Please sign in to comment.