Skip to content

Commit

Permalink
Add EnumeratorBuilder abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
sambostock committed Jan 27, 2021
1 parent 27d1404 commit 3e19856
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 18 deletions.
2 changes: 1 addition & 1 deletion app/jobs/maintenance_tasks/task_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def retry_on(*, **)
def build_enumerator(_run, cursor:)
context = Task::EnumerationContext.new(cursor: cursor || @run.cursor)

@task.enumerator(context: context)
@task.enumerator_builder.enumerator(context: context)
end

# Performs task iteration logic for the current input returned by the
Expand Down
8 changes: 7 additions & 1 deletion app/tasks/maintenance_tasks/active_record_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ class ActiveRecordTask < Task

# TODO: specify abstract_class

EnumeratorBuilder = Struct.new(:collection) do
def enumerator(context:)
enumerator_builder.active_record_on_records(collection, cursor: context.cursor)
end
end

def enumerator(context:)
collection = self.collection
assert_relation!(collection)

enumerator_builder.active_record_on_records(collection, cursor: context.cursor)
EnumeratorBuilder.new(collection)
end

def collection
Expand Down
8 changes: 7 additions & 1 deletion app/tasks/maintenance_tasks/array_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ class ActiveRecordTask < Task

# TODO: Specify abstract_class

EnumeratorBuilder = Struct.new(:collection) do
def enumerator(context:)
enumerator_builder.array(collection, cursor: context.cursor)
end
end

def enumerator(context:)
collection = self.collection
assert_array!(collection)

enumerator_builder.array(collection, cursor: context.cursor)
EnumeratorBuilder.new(collection)
end

def collection
Expand Down
10 changes: 8 additions & 2 deletions app/tasks/maintenance_tasks/csv_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ module MaintenanceTasks
class CsvTask < Task
# TODO: specify abstract_class

EnumeratorBuilder = Struct.new(:collection) do
def enumerator(context:)
JobIteration::CsvEnumerator.new(collection).rows(cursor: context.cursor)
end
end

# The contents of a CSV file to be processed by a Task.
#
# @return [String] the content of the CSV file to process.
attr_accessor :csv_content

def enumerator(context:)
JobIteration::CsvEnumerator.new(collection).rows(cursor: context.cursor)
def enumerator_builder(context:)
EnumeratorBuilder.new(collection)
end

# The number of rows to be processed. Excludes the header row from the count
Expand Down
4 changes: 2 additions & 2 deletions app/tasks/maintenance_tasks/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ def load_constants
#
# @raise [NotImplementedError] with a message advising subclasses to
# implement an override for this method.
def enumerator(context:)
def enumerator_builder(context:)
raise NotImplementedError,
"#{self.class.name} must implement `enumerator` or inherit from a class which does"
"#{self.class.name} must implement `#{__method__}` or inherit from a class which does"
# TODO: Could make error string list available adapters
end

Expand Down
28 changes: 17 additions & 11 deletions example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,28 @@ def process(row) BetaFlag[:whatever].enable(row.shop_id) end
end

class PaymentTask < MaintenanceTasks::Task
# Consumers implement .enumerator instead of .collection, without having to
# know that other tasks actually also use .enumerator internally
def enumerator(context:)
Enumerator.new do |yielder|
cursor = context.cursor
loop do
page = cursor ? InvoiceAPI.fetch(after: cursor) : InvoiceAPI.fetch_all
break if page.empty?
page.each do |invoice|
cursor = invoice.id
yielder.yield(invoice, cursor)
# Consumers implement .build_enumerator instead of .collection, without
# having to know that other tasks actually also use it internally
class EnumeratorBuilder
def enumerator(context:)
Enumerator.new do |yielder|
cursor = context.cursor
loop do
page = cursor ? InvoiceAPI.fetch(after: cursor) : InvoiceAPI.fetch_all
break if page.empty?
page.each do |invoice|
cursor = invoice.id
yielder.yield(invoice, cursor)
end
end
end
end
end

def build_enumerator
Enumerator.new
end

# Again, can be implemented if appropriate
def count() InvoiceAPI.unpaid_count end

Expand Down

0 comments on commit 3e19856

Please sign in to comment.