Skip to content

Commit

Permalink
Change cursor from bigint to string
Browse files Browse the repository at this point in the history
Working on the upcoming support for tasks backed by custom enumerators
surfaced the need for non-numeric cursors.

For instance, one might have a task that iterates over resources backed
by some API providing its own opaque string cursor, which would be
impossible to serialize to a bigint column.

As such, this changes the maintenance_tasks_runs.cursor column to be a
string. For this to work, we must deserialize the cursor back to an
integer in the Array and CSV collection cases, while the ActiveRecord
case is handled transparently.

Co-authored-by: Adrianna Chang <[email protected]>
Co-authored-by: Sam Bostock <[email protected]>
  • Loading branch information
2 people authored and etiennebarrie committed Jun 22, 2023
1 parent eeee3f4 commit 5d107fe
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 6 deletions.
6 changes: 3 additions & 3 deletions app/jobs/concerns/maintenance_tasks/task_job_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ def build_enumerator(_run, cursor:)
batch_size: collection.batch_size,
)
when Array
enumerator_builder.build_array_enumerator(collection, cursor: cursor)
enumerator_builder.build_array_enumerator(collection, cursor: cursor&.to_i)
when BatchCsvCollectionBuilder::BatchCsv
JobIteration::CsvEnumerator.new(collection.csv).batches(
batch_size: collection.batch_size,
cursor: cursor,
cursor: cursor&.to_i,
)
when CSV
JobIteration::CsvEnumerator.new(collection).rows(cursor: cursor)
JobIteration::CsvEnumerator.new(collection).rows(cursor: cursor&.to_i)
else
raise ArgumentError, <<~MSG.squish
#{@task.class.name}#collection must be either an
Expand Down
20 changes: 20 additions & 0 deletions db/migrate/20210219212931_change_cursor_to_string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

class ChangeCursorToString < ActiveRecord::Migration[6.0]
# This migration will clear all existing data in the cursor column for
# both MySQL and PostgresQL. Ensure no Tasks are paused when this migration
# is deployed, or they will be resumed from the start.
# Running tasks are able to gracefully handle this change, even if
# interrupted.
def up
change_table(:maintenance_tasks_runs) do |t|
t.change(:cursor, :string)
end
end

def down
change_table(:maintenance_tasks_runs) do |t|
t.change(:cursor, :bigint)
end
end
end
2 changes: 1 addition & 1 deletion test/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
t.bigint "tick_count", default: 0, null: false
t.bigint "tick_total"
t.string "job_id"
t.bigint "cursor"
t.string "cursor"
t.string "status", default: "enqueued", null: false
t.string "error_class"
t.string "error_message"
Expand Down
4 changes: 2 additions & 2 deletions test/jobs/maintenance_tasks/task_job_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,11 @@ class << self

TaskJob.perform_now(@run)

assert_equal 0, @run.reload.cursor
assert_equal "0", @run.reload.cursor
end

test ".perform_now starts job from cursor position when job resumes" do
@run.update!(cursor: 0)
@run.update!(cursor: "0")

Maintenance::TestTask.any_instance.expects(:process).once.with(2)

Expand Down

0 comments on commit 5d107fe

Please sign in to comment.