-
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
Use BinaryBlob to store ManagerRefresh::Target payload #16413
Use BinaryBlob to store ManagerRefresh::Target payload #16413
Conversation
cf0b1e9
to
164b808
Compare
app/models/manager_refresh/target.rb
Outdated
payload_blob = BinaryBlob.find(payload_id) | ||
@options[:payload] = payload_blob.binary | ||
payload_blob.destroy | ||
end |
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.
maybe something like this would be clearer?
if options[:payload]
@options[:payload_id] = BinaryBlob.create!(:binary => options[:payload]).id
elsif options[:payload_id]
payload_blob = BinaryBlob.find(options[:payload_id])
@options[:payload] = payload_blob.binary
payload_blob.destroy
end
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 would prefer the actual database access to be moved out of here.
But the if
/ elsif
removes my concern that we are creating the Blob
and then deleting it a few instructions later
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.
So there is another problem and the reason why I asked about the 'purging'. To maintain the current workflow of: if there is refresh and the process dies, the restarted process will pick up the same refresh again. That means we can't destroy the payload as part of input. We need to refresh first, then delete the payload in post refresh or some scheduled purger looking at orphaned payloads.
app/models/manager_refresh/target.rb
Outdated
|
||
payload_id = options[:payload_id] | ||
if payload_id | ||
payload_blob = BinaryBlob.find(payload_id) |
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 we move this to a separate call?
May need to change change k8s InventoryCollectorMixin#parse_target_from_notice
and TargetCollection#add_target
plus there are many uses of Target#load
e171d87
to
f7b8a9b
Compare
ok. |
@kbrock yes now it is on the caller to call |
Is there any purging on BinaryBlob table, in case we leak them?
|
Not that I'm aware of we'll have to add it |
@agrare seems like the added specs are failing :-) |
@Ladas working on it :) |
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.
Ok, so we will probably need purging, in a case that this fails during post refresh.
But for now, it looks good 👍 (after CI passes)
app/models/manager_refresh/target.rb
Outdated
payload_blob = BinaryBlob.find(payload_id) | ||
@options[:payload] = payload_blob.binary | ||
payload_blob.destroy | ||
end |
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.
So there is another problem and the reason why I asked about the 'purging'. To maintain the current workflow of: if there is refresh and the process dies, the restarted process will pick up the same refresh again. That means we can't destroy the payload as part of input. We need to refresh first, then delete the payload in post refresh or some scheduled purger looking at orphaned payloads.
how does consuming work off MiqQueue normally work?
at what point is the row claimed/marked done/deleted? any chance to
atomically delete blobs together with it?
|
4e81f9f
to
5fcfb49
Compare
Okay tests updated for the new interface |
5fcfb49
to
326371c
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.
Awesome
The queue item is typically destroyed here destroy_potentially_stale_record after it is delivered. We also destroy queue items here and here. |
83816cb
to
0078066
Compare
app/models/miq_queue.rb
Outdated
@@ -19,6 +19,7 @@ | |||
# | |||
class MiqQueue < ApplicationRecord | |||
belongs_to :handler, :polymorphic => true | |||
has_many :binary_blobs, :as => :resource, :dependent => :nullify |
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.
The dependent bit is going to add a query to every delete...we may just want to put nothing here.
Can we extract purging into a separate PR? I think that one is less controversial. |
f0d971c
to
e8a467c
Compare
Yes, #16524 |
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 great now
Seems to be a weird github bug, can't reply to the comment directly
@Fryguy We would have to change the purging scope which currently looks for The best I can come up with is |
e8a467c
to
6449ac2
Compare
app/models/binary_blob/purging.rb
Outdated
@@ -13,7 +13,7 @@ def purge_window_size | |||
end | |||
|
|||
def purge_scope(_older_than = nil) | |||
where(:resource => nil) | |||
where(:resource_type => 'MiqQueue').where.not('resource_id in (select id from miq_queue)') |
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.
hm, this would explode, given select id from miq_queue
would unpack the whole miq queue (that can go to milions)
refresh_queue_items = MiqQueue.where(:method_name => 'refresh') # rails is smart enough to add .select(:id)
where(:resource_type => 'MiqQueue').where.not(:resource_id => refresh_queue_items)
I think :method_name => 'refresh'
might be enough to fetch existing refresh MiqQueue items, or maybe more from https://github.com/Ladas/manageiq/blob/acf2ad8e29b9e70858fc99e22614d2112312066c/app/models/ems_refresh.rb#L162 ?
Is purging Zone agnostic? Or we should limit it by zone, if each zone has its own purger?
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.
query looks fast enough in hundred k world
2.4.2 :019 > BinaryBlob.where(:resource_type => 'MiqQueue').where.not(:resource_id => refresh_queue_items).count
(92.6ms) SELECT COUNT(*) FROM "binary_blobs" WHERE "binary_blobs"."resource_type" = $1 AND ("binary_blobs"."resource_id" NOT IN (SELECT "miq_queue"."id" FROM "miq_queue" WHERE "miq_queue"."method_name" = $2)) [["resource_type", "MiqQueue"], ["method_name", "refresh"]]
Query Trace > lib/extensions/ar_virtual.rb:741:in `calculate'
=> 351020
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 only care about purging blobs related to MiqQueue
? If not, you can use the polymorphic orphan purging I added in #16754
It uses a join so it should be a bit more efficient than the subquery you have here. Also it won't pull back the ids to the server at all.
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.
@carbonin 👍 looks much better, I'll switch to that when yours is merged
6449ac2
to
0855779
Compare
in a perfect world, knowing a blob is used would be hidden - so when we use a different queuing mechanism, it can be used without too much of a change. Having said that, this change should be a good performance improvement. |
0855779
to
006e4b0
Compare
@Fryguy what do you think about this? This will get the |
This pull request is not mergeable. Please rebase and repush. |
Tie MiqQueue to BinaryBlob
Fill resource id only to new targets, to avoid growing query.
006e4b0
to
41f3e1d
Compare
Checked commits agrare/manageiq@fe72473~...41f3e1d with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 app/models/ems_refresh.rb
app/models/miq_queue.rb
spec/models/manager_refresh/target_spec.rb
|
@Fryguy Ok to merge this? |
In order to parse pod events for pods which might already be deleted we
need to pass the payload for the pod with the refresh target. This can
however lead to very large queue items as the full payload for a pod can
be quite large.
This moves the payload to a binary blob when the target is created with
a payload, and loads the binary blob then deletes it when the target is
created with a payload_id.
Related: ManageIQ/manageiq-providers-kubernetes#164