-
Notifications
You must be signed in to change notification settings - Fork 898
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
Add tool to remove grouping from report results #17589
Add tool to remove grouping from report results #17589
Conversation
c0e3a2a
to
daf38a7
Compare
rr.report.extras = report.extras.except!(:grouping) | ||
rr.report.save | ||
rr.save | ||
unless rr.reload.report.extras.key?(:grouping) |
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.
Is it really necessary to reload here? Perhaps you can do this instead?
unless rr.save
...
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.
My 2 cents: I don't mind the verbosity of reloading this from the database to confirm it is changed there (since it being fixed there is what matters most).
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.
Honestly, I was thinking of not doing reload due to the performance problem, but while developing this, I was concerned that I wasn't really saving the correct value back into the database. Therefore, I thought it was worthwhile to pay a little overhead to ensure we are actually doing the right thing.
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.
Looks good. Have a few things of concern that you might want to look at, specifically the rr.report.save
section.
Other than that, I don't really mind the verbose file name (the one that is currently in the PR description, not the current one). I think keeping it as a super crappy long name will give use a small push to remove it from the repo and make it a migration.
|
||
puts "Using options: #{opts.inspect}" | ||
|
||
# Load rails after trollop options are set. No one wants to wait for -h. |
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.
You are a developer after my own heart. 😍
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 waited twice and got so I changed it
|
||
if report.extras.key?(:grouping) | ||
rr.report.extras = report.extras.except!(:grouping) | ||
rr.report.save |
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 don't think you want this. The id
for this should be nil
, and this should just be a copy of that record. Doing a .save
here would be doing a CREATE
basically, right?
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.
Yeah, good point. I wrote this at first and didn't come back to it. Now that it's easy to test and use, I can verify each line is needed and ✂️ 👊 🚽 anything that doesn't make the cut.
require File.expand_path('../config/environment', __dir__) | ||
if opts[:dry_run] | ||
puts "Running in dry-run, changes will be rolled back when complete." | ||
ActiveRecord::Base.connection.begin_transaction(joinable: false) |
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.
Do we want to be doing this regardless if we are doing a dry run? Maybe we should be doing .save!
as well so if it fails, we rollback and can do some investigation.
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.
Ah, interesting point. What if you do the whole table in one invocation? Will that blow up the transaction log? I'm thinking there's thousands of rows typically, not tens or hundreds of thousands.
next if report.nil? || report.extras.nil? | ||
|
||
if report.extras.key?(:grouping) | ||
rr.report.extras = report.extras.except!(:grouping) |
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.
Pendantic: If you wanted to use less code, you could just do a rr.report.extras.delete(:grouping)
.
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.
Truth. I'll fix.
@@ -0,0 +1,47 @@ | |||
#!/usr/bin/env ruby | |||
require 'trollop' |
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.
require 'optparse'
for lyfe!!1!
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'm waiting for @kbrock to rename trollor to optimal or whatever we decided. 🕐
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.
or trollop
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 always favor stdlib things when possible, so that was what my comment was all about.
#!/usr/bin/env ruby | ||
require 'trollop' | ||
|
||
ARGV.shift if ARGV[0] == '--' # if invoked with rails runner |
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.
Uh, who would really want to deal with a slow -h
to do this...
Also, can this work like that? I have had troubles in the past requiring config/environment
twice in one script, but maybe this will be fine.
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 is a thing we've done since the dawn of time for tools. I suppose it's fine to not do this and expect to be run with ruby.
fixed = 0 | ||
MiqReportResult.find_each(batch_size: opts[:batch_size]).with_index do |rr, i| | ||
break if opts[:count] > 0 && i == opts[:count] | ||
report = rr.report |
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.
Pedantic: Is this really needed? You dance between using both rr.report
and report
below, and the omission of rr.
isn't really saving you much on character count.
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.
🕺 yeah. I wasn't in love with this either. I'll rework it.
rr.report.extras = report.extras.except!(:grouping) | ||
rr.report.save | ||
rr.save | ||
unless rr.reload.report.extras.key?(:grouping) |
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.
My 2 cents: I don't mind the verbosity of reloading this from the database to confirm it is changed there (since it being fixed there is what matters most).
@jrafanie tsk tsk. Using non-hashrocket syntax... You monster... |
🙈 |
daf38a7
to
b343e61
Compare
I don't know what you're saying, there's no 1.9 syntax here. 😉 |
b343e61
to
382060f
Compare
|
||
if defined?(Rails) | ||
puts "Warning: Rails is already loaded! Please do not invoke using rails runner. Exiting with help text.\n\n" | ||
Trollop.educate |
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.
@NickLaMuro changed the --
handling to just warn, print the help text and exit. Let me know if this is overkill.
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.
Works for me. I didn't realize what you had was standard for the tools/
dir, so it was more of a "is this okay" out of naivety than anything else.
|
||
if rr.report.extras.key?(:grouping) | ||
rr.report.extras.delete(:grouping) | ||
rr.save! |
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.
@NickLaMuro I am using save!
now and rescuing on error.
opts = Trollop.options do | ||
banner "Remove extras[:grouping] from MiqReportResult#report column.\n\nUsage: ruby #{$PROGRAM_NAME} [options]\n\nOptions:\n\t" | ||
opt :dry_run, "For testing, rollback any changes when the script exits.", :short => :none, :default => false | ||
opt :batch_size, "Limit memory usage by process this number of report results at a time.", :default => 50 |
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.
Does 50 batch size make sense? Considering the size of these, I wanted extra queries instead of possibly bloating the memory of the process.
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 think so. The deserialization is probably going to hit us harder than the queries time themselves. I don't see this as being an issue with N+1
's.
You crazy bot
Bot, these aren't the complaints you're looking for. |
382060f
to
fec179d
Compare
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 looks good on my end. I assume that everything is working as expected in testing it as well, so I think we can ship.
The comments that I made along with this are not worth holding up the review.
|
||
total += 1 | ||
rescue => err | ||
puts "\nWarning: Rolling back all changes since an error occurred on MiqReportResult with id: #{rr.try(:id)}: #{err.message}" |
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.
Pandantic: Should this be warn
instead of puts
?
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.
yeah, I had warn but we don't warn
elsewhere. 🤷♂️
next if rr.report.nil? || rr.report.extras.nil? | ||
|
||
if rr.report.extras.key?(:grouping) | ||
rr.report.extras.except!(:grouping) |
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 may have told you to use the non-bang version of this... oops...
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.
lol, i confirmed it wasn't working and could then make it work using the bang method
if opts[:dry_run] | ||
puts "Running in dry-run, all changes will be rolled back when complete." | ||
|
||
at_exit do |
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.
Just because I am not sure: I assume that at_exit
will still fire after a exit 1
, right?
(Nick could probably just go test this in a ruby script himself...)
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.
yeah, good point. I'll test that
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.
No need, I already did:
$ ruby -e "at_exit { puts 'foo' }; exit 42"
foo
$ echo $?
42
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 did several tests of dry run so I'm pretty confident it works. It's a little messy how I'm doing it right now but I can't think of a better way to handle the begin/commit/rollback for dry-run/error/exit
@carbonin Can you review/merge? 🙇 |
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.
One question about a condition.
Also, from a high level, would it make sense for the guts of this to be a method on MiqReportResult
(#clear_report_grouping
perhaps?) rather than embedding all the logic in an untested tool?
Then, in a follow-up, we could use this method after generating the html data so future users won't need this tool.
if rr.report.extras.key?(:grouping) | ||
rr.report.extras.except!(:grouping) | ||
rr.save! | ||
if rr.reload.report.extras.key?(:grouping) |
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.
When would this happen?
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 was here before I changed line 43 from .save
to .save!
and added the begin
/rescue
around it. It's unlikely to happen now but I left this because it seemed odd to leave out one of the three cases below:
"doesn't need fixing"
"fixed"
"could NOT be fixed"
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.
Random thing I noticed while reading through some of the other review comments. Low priority.
MiqReportResult.find_each(:batch_size => opts[:batch_size]).with_index do |rr, i| | ||
begin | ||
break if opts[:count].positive? && i == opts[:count] | ||
next if rr.report.nil? || rr.report.extras.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.
Sorry, just noticed this, but doesn't this next
break the total
count accuracy?
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.
yeah, good 👁. I'll fix that.
https://bugzilla.redhat.com/show_bug.cgi?id=1590908 Some aggregation information was persisted into the miq_report_results table in the report column's `extras[:grouping]` section. We don't need the grouping after we've generated the html data. This tool removes this from each row in the table. The default options will process the whole table in batches of 50 at a time and will persist all changes. If you run it with -h, you'll receive a help banner: ``` Remove extras[:grouping] from MiqReportResult#report column. Usage: ruby tools/remove_grouping_from_report_results.rb [options] Options: --dry-run For testing, rollback any changes when the script exits. -b, --batch-size=<i> Limit memory usage by process this number of report results at a time. (Default: 50) -c, --count=<i> Stop checking after this number of report results. (Default: 0) -h, --help Show this message ``` Example output looks like this: ``` ruby tools/remove_grouping_from_report_results.rb -c 11 Using options: {:dry_run=>false, :batch_size=>50, :count=>11, :help=>false, :count_given=>true} ** Using session_store: ActionDispatch::Session::MemCacheStore MiqReportResult: 22000000000001 doesn't need fixing MiqReportResult: 22000000000002 doesn't need fixing MiqReportResult: 22000000000003 fixed MiqReportResult: 22000000000004 doesn't need fixing MiqReportResult: 22000000000005 doesn't need fixing MiqReportResult: 22000000000006 fixed MiqReportResult: 22000000000007 doesn't need fixing MiqReportResult: 22000000000008 doesn't need fixing MiqReportResult: 22000000000009 doesn't need fixing MiqReportResult: 22000000000010 doesn't need fixing MiqReportResult: 22000000000011 fixed Processed 11 rows. 1 were fixed. 13.170998 seconds ```
fec179d
to
7a54727
Compare
Checked commits jrafanie/manageiq@8b4fe07~...7a54727 with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 tools/remove_grouping_from_report_results.rb
|
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 am @NickLaMuro, and I (still) approve of these changes.
@carbonin it's green now 👍 |
…esults Add tool to remove grouping from report results (cherry picked from commit c36370d) https://bugzilla.redhat.com/show_bug.cgi?id=1594387
Fine backport details:
|
…esults Add tool to remove grouping from report results (cherry picked from commit c36370d) https://bugzilla.redhat.com/show_bug.cgi?id=1594386
Gaprindashvili backport details:
|
https://bugzilla.redhat.com/show_bug.cgi?id=1590908
Some aggregation information was persisted into the miq_report_results
table in the report column's
extras[:grouping]
section. We don't needthe grouping after we've generated the html data. This tool removes
this from each row in the table.
The default options will process the whole table in batches of 50 at a
time and will persist all changes.
If you run it with -h, you'll receive a help banner:
Example output looks like this: