diff --git a/app/jobs/solid_cable/trim_job.rb b/app/jobs/solid_cable/trim_job.rb index 57dc8a3..6dc0336 100644 --- a/app/jobs/solid_cable/trim_job.rb +++ b/app/jobs/solid_cable/trim_job.rb @@ -2,8 +2,17 @@ module SolidCable class TrimJob < ActiveJob::Base - def perform - ::SolidCable::Message.trimmable.delete_all + def perform(id = ::SolidCable::Message.maximum(:id)) + return unless (id % (trim_batch_size / 2)).zero? + + ::SolidCable::Message.trimmable. + limit(trim_batch_size).non_blocking_lock.delete_all + end + + private + + def trim_batch_size + ::Solidcable.trim_batch_size end end end diff --git a/app/models/solid_cable/record.rb b/app/models/solid_cable/record.rb index f30bb58..a36c424 100644 --- a/app/models/solid_cable/record.rb +++ b/app/models/solid_cable/record.rb @@ -5,5 +5,13 @@ class Record < ActiveRecord::Base self.abstract_class = true connects_to(**SolidCable.connects_to) if SolidCable.connects_to.present? + + def self.non_blocking_lock + if SolidCable.use_skip_locked + lock(Arel.sql("FOR UPDATE SKIP LOCKED")) + else + lock + end + end end end diff --git a/lib/action_cable/subscription_adapter/solid_cable.rb b/lib/action_cable/subscription_adapter/solid_cable.rb index c33c894..c996726 100644 --- a/lib/action_cable/subscription_adapter/solid_cable.rb +++ b/lib/action_cable/subscription_adapter/solid_cable.rb @@ -15,9 +15,9 @@ def initialize(*) end def broadcast(channel, payload) - ::SolidCable::Message.broadcast(channel, payload) + id = ::SolidCable::Message.broadcast(channel, payload).rows.flatten.max - ::SolidCable::TrimJob.perform_now if ::SolidCable.autotrim? + ::SolidCable::TrimJob.perform_now(id) if ::SolidCable.autotrim? end def subscribe(channel, callback, success_callback = nil) diff --git a/lib/solid_cable.rb b/lib/solid_cable.rb index 4ee95b3..93ae7d6 100644 --- a/lib/solid_cable.rb +++ b/lib/solid_cable.rb @@ -26,6 +26,18 @@ def autotrim? cable_config.autotrim != false end + def trim_batch_size + if (size = cable_config.trim_batch_size.to_i).zero? + 100 + else + size + end + end + + def use_skip_locked + cable_config.use_skip_locked != false + end + private def cable_config diff --git a/test/solid_cable_test.rb b/test/solid_cable_test.rb index b06b2f5..e0a3a00 100644 --- a/test/solid_cable_test.rb +++ b/test/solid_cable_test.rb @@ -26,4 +26,20 @@ class SolidCableTest < ActiveSupport::TestCase assert SolidCable.autotrim? end end + + test "default trim_batch_size is 100" do + assert_equal 100, SolidCable.trim_batch_size + end + + test "trim_batch_size when set badly" do + with_cable_config trim_batch_size: "weird" do + assert_equal 100, SolidCable.trim_batch_size + end + end + + test "trim_batch_size when set" do + with_cable_config trim_batch_size: 42 do + assert_equal 42, SolidCable.trim_batch_size + end + end end