-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose ActiveJob ability to customize the columns used to order the cursor #859
Conversation
459edc3
to
e17aba3
Compare
app/models/maintenance_tasks/task.rb
Outdated
@@ -21,6 +21,9 @@ class NotFoundError < NameError; end | |||
# @api private | |||
class_attribute :collection_builder_strategy, default: NullCollectionBuilder.new | |||
|
|||
# As defined by JobIteration::EnumeratorBuilder#build_active_record_enumerator_on_records as `columns` | |||
class_attribute :cursor_columns, default: nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I searched for a way to let subclasses of MaintenanceTasks::Task
customize how the enumerator_builder
instantiates the underlying relation, without success.
Using a class_attribute
as an alternative. Is it appropriate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be overridden by specific tasks, so I think the best thing to do is provide a simple method like collection
that can be overridden. A class variable doesn't seem necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TY!
I understand that JobIteration::ActiveRecordBatchEnumerator#initialize
here will raise if the collection includes an order by
clause and hence that
- the collection provided to
JobIteration::ActiveRecordBatchEnumerator#initialize
cannot be ordered - an explicit set of ordering
columns
must be given toJobIteration::ActiveRecordBatchEnumerator#initialize
if relation.arel.orders.present? || relation.arel.taken.present?
raise JobIteration::ActiveRecordCursor::ConditionNotSupportedError
end
@base_relation = relation.reorder(@columns.join(","))
MaintenanceTasks::Task
could
- retrieve the order columns from the relation returned by
collection
- reorder the the relation returned by
collection
so it is not ordered anymore - provide the retrieved order columns to the
JobIteration::ActiveRecordBatchEnumerator#initialize
However it would make more sense to let JobIteration::ActiveRecordBatchEnumerator
itself
- support that the collection is ordered and
- derive what are the cursor columns.
For active_record_on_records
, it seems that we'd also have to make sure that the relation and columns provided to JobIteration::ActiveRecordEnumerator#initialize
are consistent.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I misunderstood your comment, got it after rereading more carefully: expose an instance method instead of a class attribute. I find that the class attribute conveys better the intent of customizing the class. Will push a commit to go as you suggest, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
e17aba3
to
b6057d8
Compare
enumerator_builder.active_record_on_records( | ||
collection, | ||
cursor: cursor, | ||
**{ columns: @task.class.cursor_columns }.compact, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the compact
? Isn't better to check if cursor_columns
are set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used this style because I had not checked in depth how active_record_on_records
would behave if passed a nil
for the columns
argument. Hence I wanted to only provide the columns
argument if it was set. I then used compact
to avoid an if-then-else.
I have checked that active_record_on_records
behaves the same way if the columns
argument is absent or nil
. It does because JobIteration::ActiveRecordEnumerator#initialize
here defaults columns
to nil
.
-> updated to always provide columns: @task.class.cursor_columns
in the Provide columns argument unconditionally to active_record_on_records commit.
app/models/maintenance_tasks/task.rb
Outdated
@@ -21,6 +21,9 @@ class NotFoundError < NameError; end | |||
# @api private | |||
class_attribute :collection_builder_strategy, default: NullCollectionBuilder.new | |||
|
|||
# As defined by JobIteration::EnumeratorBuilder#build_active_record_enumerator_on_records as `columns` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you improve this documentation telling what this does instead of linking to method in another library? For the sake of this library, this method is only to configure which column will be used in the Active Record enumerator. Let's explain this and then, we can link to the other library, but if we are going to do that, we should really link to the library documentation, not just mention the reference of the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement proposal in Document the cursor_columns attribute inline commit.
test/application_system_test_case.rb
Outdated
@@ -5,6 +5,7 @@ | |||
require "action_dispatch/system_testing/server" | |||
|
|||
ActionDispatch::SystemTesting::Server.silence_puma = true | |||
Webdrivers::Chromedriver.required_version = "114.0.5735.90" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can remove this now I believe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TY - Dropped the commit.
@bbraschi are you still interested in working on this? |
@gmcgibbon If you have you have the time to bring this to a conclusion, through this PR or another, please do. Else, I can work on it at the end of Jan 2024. |
f4e0c5b
to
8ec0c18
Compare
enumerator_builder.active_record_on_records( | ||
collection, | ||
cursor: cursor, | ||
**{ columns: @task.class.cursor_columns }.compact, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used this style because I had not checked in depth how active_record_on_records
would behave if passed a nil
for the columns
argument. Hence I wanted to only provide the columns
argument if it was set. I then used compact
to avoid an if-then-else.
I have checked that active_record_on_records
behaves the same way if the columns
argument is absent or nil
. It does because JobIteration::ActiveRecordEnumerator#initialize
here defaults columns
to nil
.
-> updated to always provide columns: @task.class.cursor_columns
in the Provide columns argument unconditionally to active_record_on_records commit.
@@ -54,6 +58,7 @@ def build_enumerator(_run, cursor:) | |||
collection.relation, | |||
cursor: cursor, | |||
batch_size: collection.batch_size, | |||
**{ columns: @task.class.cursor_columns }.compact, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have checked that active_record_on_batch_relations
behaves the same way if the columns
argument is absent or nil
. It does because JobIteration::ActiveRecordBatchEnumerator#initialize
here defaults columns
to nil
.
-> updated to always provide columns: @task.class.cursor_columns
in the Provide columns argument unconditionally to active_record_on_records commit.
app/models/maintenance_tasks/task.rb
Outdated
@@ -21,6 +21,9 @@ class NotFoundError < NameError; end | |||
# @api private | |||
class_attribute :collection_builder_strategy, default: NullCollectionBuilder.new | |||
|
|||
# As defined by JobIteration::EnumeratorBuilder#build_active_record_enumerator_on_records as `columns` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement proposal in Document the cursor_columns attribute inline commit.
@rafaelfranca , @gmcgibbon sorry for the PR getting stalled. Tried to take your comments into account, please review when you can. TY |
app/models/maintenance_tasks/task.rb
Outdated
@@ -21,6 +21,9 @@ class NotFoundError < NameError; end | |||
# @api private | |||
class_attribute :collection_builder_strategy, default: NullCollectionBuilder.new | |||
|
|||
# As defined by JobIteration::EnumeratorBuilder#build_active_record_enumerator_on_records as `columns` | |||
class_attribute :cursor_columns, default: nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be overridden by specific tasks, so I think the best thing to do is provide a simple method like collection
that can be overridden. A class variable doesn't seem necessary.
`job-iteration` supports configuring which columns are used to order the cursor. This commit provides a way to expose this ability in the `maintenance-tasks` gem.
1bbfa40
to
9ff94ee
Compare
JobIteration::ActiveRecordCursor#condition
adds anorder by
clause to the relation returned by thecollection
method. It default to order on theid
column, seeJobIteration::ActiveRecordCursor#initialize
.Ordering on
id
only can degrade performance significantly depending on which indexes are defined.job-iteration
supports configuring which columns are used to order the cursor. This PR explores a way to expose this ability in themaintenance-tasks
gem.