lib/job-iteration/enumerator_builder.rb in job-iteration-1.3.6 vs lib/job-iteration/enumerator_builder.rb in job-iteration-1.4.0

- old
+ new

@@ -2,10 +2,11 @@ require_relative "./active_record_batch_enumerator" require_relative "./active_record_enumerator" require_relative "./csv_enumerator" require_relative "./throttle_enumerator" +require_relative "./nested_enumerator" require "forwardable" module JobIteration class EnumeratorBuilder extend Forwardable @@ -17,14 +18,16 @@ # Enumerators without wrapping them in # `enumerator_builder.wrap(custom_enum)`. We don't do this yet for backwards # compatibility with raw calls to EnumeratorBuilder. Think of these wrappers # the way you should a middleware. class Wrapper < Enumerator - def self.wrap(_builder, enum) - new(-> { enum.size }) do |yielder| - enum.each do |*val| - yielder.yield(*val) + class << self + def wrap(_builder, enum) + new(-> { enum.size }) do |yielder| + enum.each do |*val| + yielder.yield(*val) + end end end end end @@ -97,11 +100,11 @@ # again. Similarly, if the value gets updated to a lesser value than the curor's value, it will get skipped. def build_active_record_enumerator_on_records(scope, cursor:, **args) enum = build_active_record_enumerator( scope, cursor: cursor, - **args + **args, ).records wrap(self, enum) end # Builds Enumerator from Active Record Relation and enumerates on batches of records. @@ -112,48 +115,83 @@ # For the rest of arguments, see documentation for #build_active_record_enumerator_on_records def build_active_record_enumerator_on_batches(scope, cursor:, **args) enum = build_active_record_enumerator( scope, cursor: cursor, - **args + **args, ).batches wrap(self, enum) end # Builds Enumerator from Active Record Relation and enumerates on batches, yielding Active Record Relations. # See documentation for #build_active_record_enumerator_on_batches. def build_active_record_enumerator_on_batch_relations(scope, wrap: true, cursor:, **args) enum = JobIteration::ActiveRecordBatchEnumerator.new( scope, cursor: cursor, - **args + **args, ).each enum = wrap(self, enum) if wrap enum end def build_throttle_enumerator(enum, throttle_on:, backoff:) JobIteration::ThrottleEnumerator.new( enum, @job, throttle_on: throttle_on, - backoff: backoff + backoff: backoff, ).to_enum end def build_csv_enumerator(enumerable, cursor:) CsvEnumerator.new(enumerable).rows(cursor: cursor) end + # Builds Enumerator for nested iteration. + # + # @param enums [Array<Proc>] an Array of Procs, each should return an Enumerator. + # Each proc from enums should accept the yielded items from the parent enumerators + # and the `cursor` as its arguments. + # Each proc's `cursor` argument is its part from the `build_enumerator`'s `cursor` array. + # @param cursor [Array<Object>] array of offsets for each of the enums to start iteration from + # + # @example + # def build_enumerator(cursor:) + # enumerator_builder.nested( + # [ + # ->(cursor) { + # enumerator_builder.active_record_on_records(Shop.all, cursor: cursor) + # }, + # ->(shop, cursor) { + # enumerator_builder.active_record_on_records(shop.products, cursor: cursor) + # }, + # ->(_shop, product, cursor) { + # enumerator_builder.active_record_on_batch_relations(product.product_variants, cursor: cursor) + # } + # ], + # cursor: cursor + # ) + # end + # + # def each_iteration(product_variants_relation) + # # do something + # end + # + def build_nested_enumerator(enums, cursor:) + NestedEnumerator.new(enums, cursor: cursor).each + end + alias_method :once, :build_once_enumerator alias_method :times, :build_times_enumerator alias_method :array, :build_array_enumerator alias_method :active_record_on_records, :build_active_record_enumerator_on_records alias_method :active_record_on_batches, :build_active_record_enumerator_on_batches alias_method :active_record_on_batch_relations, :build_active_record_enumerator_on_batch_relations alias_method :throttle, :build_throttle_enumerator alias_method :csv, :build_csv_enumerator + alias_method :nested, :build_nested_enumerator private def build_active_record_enumerator(scope, cursor:, **args) unless scope.is_a?(ActiveRecord::Relation) @@ -161,10 +199,10 @@ end JobIteration::ActiveRecordEnumerator.new( scope, cursor: cursor, - **args + **args, ) end end end