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