-
Notifications
You must be signed in to change notification settings - Fork 899
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 foreign_key on the base model's name if ems_events association doesn't exist #23296
Use foreign_key on the base model's name if ems_events association doesn't exist #23296
Conversation
@kbrock any thoughts on this change? Note, event_where_clause for ems cluster is a real cluster in that it tries to do an or of all host_ids and vm ids from event streams... that feels like it will destroy performance completely. I did just the ems_cluster_id where clause for now as that's what I need to fix the issue but we'll only see timelines for events specific for that cluster, which I think is what we want. |
FactoryBot.create(:event_stream) | ||
expect(EventStream.where(obj.event_stream_filters["EmsEvent"]).to_a).to eq([event]) | ||
expect(EventStream.where(obj.event_where_clause(:ems_events)).to_a).to eq([event]) | ||
klasses = klass.constantize.descendants.collect(&:name).unshift(klass) |
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.
Note, EmsCluster does the right thing, but subclasses weren't. This test recreated reported issue so the fix above can verify the problem is addressed.
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.
FYI, without the code change, the test fails for each ems cluster subclass like below:
1) EventMixin event_stream_filters ManageIQ::Providers::InfraManager::Cluster uses ems_cluster_id and target_id and target_type
Failure/Error: expect(obj.event_stream_filters["EmsEvent"]).to eq(column => obj.id)
expected: {"ems_cluster_id"=>nil}
got: {"cluster_id"=>nil}
(compared using ==)
Diff:
@@ -1 +1 @@
-"ems_cluster_id" => nil,
+"cluster_id" => 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.
ASIDE: Really wish we were going away from descendants
.
Also, if we start with klass
, do we end up with a bunch of queries instead of one query with an IN
clause?
This error suggests there is a problem with obj.event_where_clause
, right? Looks like a missing/incorrect foreign_key
in an association. Or when building the where()
clause, it is using the wrong base class to generate the sql.
We used to use string keys instead of symbol keys because it fixed foreign keys while building sql in a generic way. Wonder if a newer version of rails changed that behavior. (it is also possible that I'm spouting a random and unrelated fact)
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 particular code is just building a spec for each of the descendant classes - this seems like an appropriate use of descendants.
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 error suggests there is a problem with
obj.event_where_clause
, right? Looks like a missing/incorrectforeign_key
in an association. Or when building thewhere()
clause, it is using the wrong base class to generate the sql.
To be fair, some event_where_clause are completely unusable in UI timelines as they do more complex joins on possibly multiple tables such as showing events for all objects under the cluster (host, vm, templates, etc.) as opposed to just events for the cluster. The first cut of event_stream_filters
tried to do just a singular column "foreign key reference" as timelines can easily be impossible to view in the UI with too many events to display.
app/models/ems_cluster.rb
Outdated
has_many :ems_events, | ||
->(cluster) { | ||
where("ems_cluster_id" => cluster.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.
at least in terms of how ems_cluster_id
is concerned, can we use foreign_key
?
And getting rid of the or
seems to change this quite a bit
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.
Absolutely. Great idea. It feels like this was a POC for a fix for the first issue of not being able to show cluster subclasses on the timelines. I had a test for the base cluster class but subclasses weren't tested so I recreated it with them and was able to fix it with the code above.
For the second question, do we show other objects on the cluster timeline such as events from vms or hosts in the cluster, I think that's secondary question. We would need to ensure the UI passes limits to display it properly. I don't know if we should cowardly refuse to try to draw a timeline with 10,000+ events on it. For now, I was going to try to fix the bug first and then open it up for discussion on how to properly display it for large number of objects/events.
Ok. so all in all, showing any even from any object in the cluster seems useful, but since the query is so bad and so many objects come back, it is not useful. This new change is cluster only events and that reduces the number of events and will speed it up a bit. I do feel we should update it to use |
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 the one change
app/models/ems_cluster.rb
Outdated
@@ -182,6 +182,17 @@ def parent_datacenter | |||
detect_ancestor(:of_type => 'EmsFolder') { |a| a.kind_of?(Datacenter) } | |||
end | |||
|
|||
has_many :ems_events, |
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.
yea. I think we can just use has_many :ems_events
.
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.
FYI, I didn't realize but we had an ems_events method that uses event_where_clause. To minimally fix this, I fixed the ems_event_filter_column.
I read this and it makes me think the change is to change the subclasses to not change the column name and just use the base class' ems_cluster_id, but that's not the change in the PR, so I don't understand. |
a55bf58
to
09f654b
Compare
Ok, fixed just this issue and didn't add event_streams association because the method already exists and uses the event_where_clause and brings back cluster, host, vms events for the cluster and not just events for the cluster. We can deal with that afterwards. |
app/models/mixins/event_mixin.rb
Outdated
@ems_event_filter_column ||= reflect_on_association(:ems_events).try(:foreign_key) || name.foreign_key | ||
@ems_event_filter_column ||= | ||
reflect_on_association(:ems_events).try(:foreign_key) || | ||
reflect_on_association(:event_streams).try(:foreign_key) || # All Events are Ems Events for some classes right now |
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.
Specifically, PhysicalSwitch defines only event_streams.
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 not right, I don't think. EventStream is the base class for all event types, both native provider events and synthetic events; EmsEvent is the sub class for only native events, MiqEvent is the subclass for synthetic events, etc. There are other subclasses for other types of events that we don't want.
EventStream.hierarchy(&:to_s)
=> {"RequestEvent"=>{}, "MiqEvent"=>{}, "CustomEvent"=>{}, "CustomButtonEvent"=>{}, "EmsEvent"=>{}}
I think Physical Switch is defined wrong and we need to fix 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.
I can hold off on fixing this issue for now until I have cycles to add the ems_events association to all the possible timeline classes. It might just be physical switches but I'll need to find out.
Putting back in WIP. I will need to revisit the timeline classes and ensure they define ems_events associations for ems_event_filter_column method. Physical switch defines only event_streams which could return ems events and policy/miq events. Also, EmsCluster defines ems_events but it's a method that uses event_where_clause which returns all events for the cluster and includes events for any host and vms in the cluster. We'll need to make that an association and possibly only return just the events for the cluster. I'm not sure if calling code relies on host/vm events come back from ems_events from the cluster. Will need to review the other timeline classes to ensure they're consistently defining ems_events associations so we can simplify the conditional. |
0f27b70
to
73e8504
Compare
@@ -2,6 +2,9 @@ class HostAggregate < ApplicationRecord | |||
include SupportsFeatureMixin | |||
include NewWithTypeStiMixin | |||
include Metric::CiMixin | |||
|
|||
# TODO: this model doesn't have an event_where_clause, doesn't have a *_id in event_streams but includes | |||
# event mixin. Track down if we need timeline events for this as they look to not be completely supported yet. |
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.
@agrare Do you know if HostAggregates can have events associated with them?
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.
See also the same question below in other models.
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.
HostAggregates are an openstack thing, I only see vm, host (like InfraManager::Host), and availability_zone in the openstack event parser
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 only model which does have events that was touched in this PR is PhysicalSwitch
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 you have any idea why event mixin was included in host aggregates?
That's ultimately the problem. I'm trying to fix a bug in an unrelated model and the inconsistency in these other models becomes readily apparent when I try to expand the tests to cover the other models that pull in the event mixin so I can cover the failure with EmsCluster subclasses. These others don't behave like the other event mixin types. I hope it's a deletion but will need to dig into that in a followup.
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 you have any idea why event mixin was included in host aggregates?
Honestly if I had to guess, they copied another model as the basis for the HostAggregate class.
The include went all the way back to the first commit in this model
commit 5be79d08113b52daa183453fdd709aba73cf7e62
Author: Scott Seago <sseago@redhat.com>
Date: Mon Jun 27 11:24:24 2016 -0400
Host aggregate model code
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.
Are we good with a TODO to kick the can down the road?
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, TODO is probably fine - no need to fix it all at once. That being said, I still want to discuss because I still don't understand the overall issue nor the fix.
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 think we'd unwind event_mixin inclusion in models that shouldn't need it.
…esn't exist EmsCluster#ems_event_filter_column was correctly ems_cluster_id, subclasses were wrong as they had cluster_id as the column. Fix PhysicalSwitch to correctly implement ems_events association. Previously, it assumed event_streams association was the same as ems_events just because all event_streams for that model have always been ems events. Instead, we implement event_streams association so we can correctly detect the foreign key in ems_event_filter_column. Fix tests to test descendant classes so we can recreate and verify the fix for EmsCluster base class and subclasses. Add HostAggregate and hysicalServerProfile to pending list as they include the mixin but don't implement the interface (event_where_clause, _id column, no ems_events association).
73e8504
to
5278c3f
Compare
ok, this is green and ready to go |
@@ -63,7 +63,7 @@ def find_one_event(assoc, order) | |||
|
|||
module ClassMethods | |||
def ems_event_filter_column | |||
@ems_event_filter_column ||= reflect_on_association(:ems_events).try(:foreign_key) || name.foreign_key | |||
@ems_event_filter_column ||= reflect_on_association(:ems_events).try(:foreign_key) || base_model.name.foreign_key |
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 there a reason why the ems_events
reflection isn't present for all base classes?
UPDATE:
Guess HostAggregate
is an example of this.
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.
see the other discussion, they should be fixed but not here.
Please can we discuss over voice before merge - I really don't understand this PR 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.
Discussed with @jrafanie and now I understand. I was struggling to understand what PhysicalSwitch had to do with EmsCluster, but it was a side-effect of testing the EmsCluster fix on subclasses, which uncovered a problem with PhysicalSwitch.
The reason cluster_id
showed up is because the subclasses of EmsCluster in the provider are typically just ManageIQ::Providers::...::Cluster
, and so name.foreign_key
is just cluster_id
.
Backported to
|
…_events-foreign-key Use foreign_key on the base model's name if ems_events association doesn't exist (cherry picked from commit 830d608)
EmsCluster#ems_event_filter_column
was correctlyems_cluster_id
,subclasses were wrong as it returned
cluster_id
as the column.Fix
PhysicalSwitch
to correctly implementems_events
association. Previously,it assumed
event_streams
association was the same asems_events
just becauseall
event_streams
for that model have always been ems events. Instead, weimplement
event_streams
association so we can correctly detect the foreignkey in
ems_event_filter_column
.Fix tests to test descendant classes so we can recreate and verify the fix for
EmsCluster
base class and subclasses. Add
HostAggregate
andPhysicalServerProfile
to pending listas they include the mixin but don't implement the interface (
event_where_clause
, _id column, noems_events
association).Fixes a UI timeline bug shown for Ems clusters as seen below:
Background: #22361 (see the table of models and desired values for ems_event_filter_column and miq_event_filter_column.)