Skip to content

Commit

Permalink
feat: add sharding support to the collection
Browse files Browse the repository at this point in the history
  • Loading branch information
marcosgz committed Aug 5, 2024
1 parent 6646e96 commit f60209d
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
43 changes: 35 additions & 8 deletions lib/esse/active_record/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ class Collection
class_attribute :batch_contexts
self.batch_contexts = {}

# Connects to a database or role (ex writing, reading, or another custom role) for the collection query
# @param [Symbol] role The role to connect to
# @param [Symbol] shard The shard to connect to
class_attribute :connect_with
self.connect_with = nil

class << self
def inspect
return super unless self < Esse::ActiveRecord::Collection
Expand All @@ -40,6 +46,7 @@ def inherited(subclass)

subclass.scopes = scopes.dup
subclass.batch_contexts = batch_contexts.dup
subclass.connect_with = connect_with&.dup
end

def scope(name, proc = nil, override: false, &block)
Expand All @@ -57,6 +64,10 @@ def batch_context(name, proc = nil, override: false, &block)

batch_contexts[name.to_sym] = proc
end

def connected_to(**kwargs)
self.connect_with = kwargs
end
end

attr_reader :start, :finish, :batch_size, :params
Expand All @@ -74,23 +85,29 @@ def initialize(start: nil, finish: nil, batch_size: nil, **params)
end

def each
dataset.find_in_batches(**batch_options) do |rows|
kwargs = params.dup
self.class.batch_contexts.each do |name, proc|
kwargs[name] = proc.call(rows, **params)
with_connection do
dataset.find_in_batches(**batch_options) do |rows|
kwargs = params.dup
self.class.batch_contexts.each do |name, proc|
kwargs[name] = proc.call(rows, **params)
end
yield(rows, **kwargs)
end
yield(rows, **kwargs)
end
end

def each_batch_ids
dataset.select(:id).except(:includes, :preload, :eager_load).find_in_batches(**batch_options) do |rows|
yield(rows.map(&:id))
with_connection do
dataset.select(:id).except(:includes, :preload, :eager_load).find_in_batches(**batch_options) do |rows|
yield(rows.map(&:id))
end
end
end

def count
dataset.except(:includes, :preload, :eager_load, :group, :order, :limit, :offset).count
with_connection do
dataset.except(:includes, :preload, :eager_load, :group, :order, :limit, :offset).count
end
end
alias_method :size, :count

Expand Down Expand Up @@ -127,6 +144,16 @@ def inspect

protected

def with_connection
if self.class.connect_with&.any?
::ActiveRecord::Base.connected_to(**self.class.connect_with) do
yield
end
else
yield
end
end

def batch_options
{
batch_size: batch_size
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require 'esse/rspec'

require 'support/config_helpers'
require 'support/sharding_hook'
require 'support/webmock'
require 'support/models'
require 'pry'
Expand Down

0 comments on commit f60209d

Please sign in to comment.