#735 Slow web search for devices

This commit is contained in:
Oliver Gorwits
2020-08-06 21:25:01 +01:00
parent 37b75eafcb
commit 3aeed20b78
3 changed files with 95 additions and 6 deletions

View File

@@ -1,3 +1,9 @@
2.046002 - 2020-08-??
[BUG FIXES]
* #735 Slow web search for devices
2.046001 - 2020-07-10
[ENHANCEMENTS]

View File

@@ -94,6 +94,30 @@ all the interface IP aliases configured on the Device.
__PACKAGE__->has_many( device_ips => 'App::Netdisco::DB::Result::DeviceIp', 'ip' );
=head2 device_ips_by_address_or_name
Returns rows from the C<device_ip> table which relate to this Device. That is,
all the interface IP aliases configured on the Device. However you probably
want to use the C<device_ips_with_address_or_name> ResultSet method instead,
so you can pass the MAC address part.
=cut
__PACKAGE__->has_many( device_ips_by_address_or_name => 'App::Netdisco::DB::Result::DeviceIp',
sub {
my $args = shift;
return {
"$args->{foreign_alias}.ip" => { -ident => "$args->{self_alias}.ip" },
-or => [
"$args->{foreign_alias}.dns" => { 'ilike', \'?' },
"$args->{foreign_alias}.alias" => { '<<=', \'?' },
"$args->{foreign_alias}.alias::text" => { 'ilike', \'?' },
],
};
},
{ cascade_copy => 0, cascade_update => 0, cascade_delete => 0 }
);
=head2 vlans
Returns the C<device_vlan> entries for this Device. That is, the list of VLANs
@@ -111,6 +135,25 @@ Returns the set of ports on this Device.
__PACKAGE__->has_many( ports => 'App::Netdisco::DB::Result::DevicePort', 'ip' );
=head2 ports_by_mac
Returns the set of ports on this Device, filtered by MAC. However you probably
want to use the C<ports_with_mac> ResultSet method instead, so you can pass the
MAC address part.
=cut
__PACKAGE__->has_many( ports_by_mac => 'App::Netdisco::DB::Result::DevicePort',
sub {
my $args = shift;
return {
"$args->{foreign_alias}.ip" => { -ident => "$args->{self_alias}.ip" },
"$args->{foreign_alias}.mac::text" => { 'ilike', \'?' },
};
},
{ cascade_copy => 0, cascade_update => 0, cascade_delete => 0 }
);
=head2 modules
Returns the set chassis modules on this Device.

View File

@@ -13,6 +13,43 @@ require Dancer::Logger;
=head1 ADDITIONAL METHODS
=head2 device_ips_with_address_or_name( $address_or_name )
Returns a correlated subquery for the set of C<device_ip> entries for each
device. The IP alias or dns matches the supplied C<address_or_name>, using
C<ILIKE>.
=cut
sub device_ips_with_address_or_name {
my ($rs, $q, $ipbind) = @_;
$q ||= '255.255.255.255/32';
return $rs->search(undef,{
# NOTE: bind param list order is significant
join => ['device_ips_by_address_or_name'],
bind => [$q, $ipbind, $q],
});
}
=head2 ports_with_mac( $mac )
Returns a correlated subquery for the set of C<device_port> entries for each
device. The port MAC address matches the supplied C<mac>, using C<ILIKE>.
=cut
sub ports_with_mac {
my ($rs, $mac) = @_;
$mac ||= '00:00:00:00:00:00';
return $rs->search(undef,{
# NOTE: bind param list order is significant
join => ['ports_by_mac'],
bind => [$mac],
});
}
=head2 with_times
This is a modifier for any C<search()> (including the helpers below) which
@@ -350,15 +387,17 @@ sub search_fuzzy {
# basic IP check is a string match
my $ip_clause = [
'me.ip::text' => { '-ilike' => $q },
'device_ips.alias::text' => { '-ilike' => $q },
'device_ips_by_address_or_name.alias::text' => { '-ilike' => $q },
];
my $ipbind = '255.255.255.255/32';
# but also allow prefix search
if (my $ip = NetAddr::IP::Lite->new($qc)) {
$ip_clause = [
'me.ip' => { '<<=' => $ip->cidr },
'device_ips.alias' => { '<<=' => $ip->cidr },
'device_ips_by_address_or_name.alias' => { '<<=' => $ip->cidr },
];
$ipbind = $ip->cidr;
}
# get IEEE MAC format
@@ -369,7 +408,9 @@ sub search_fuzzy {
or ($mac->as_ieee !~ m/$RE{net}{MAC}/)));
$mac = ($mac ? $mac->as_ieee : $q);
return $rs->search(
return $rs->ports_with_mac($mac)
->device_ips_with_address_or_name($q, $ipbind)
->search(
{
-or => [
'me.contact' => { '-ilike' => $q },
@@ -383,18 +424,17 @@ sub search_fuzzy {
},
-or => [
'me.mac::text' => { '-ilike' => $mac},
'ports.mac::text' => { '-ilike' => $mac},
'ports_by_mac.mac::text' => { '-ilike' => $mac},
],
-or => [
'me.dns' => { '-ilike' => $q },
'device_ips.dns' => { '-ilike' => $q },
'device_ips_by_address_or_name.dns' => { '-ilike' => $q },
],
-or => $ip_clause,
],
},
{
order_by => [qw/ me.dns me.ip /],
join => [qw/device_ips ports/],
distinct => 1,
}
);