]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1028795: pre-load all related bugs during show_bug initialisation
authorByron Jones <glob@mozilla.com>
Thu, 3 Jul 2014 07:36:08 +0000 (15:36 +0800)
committerByron Jones <glob@mozilla.com>
Thu, 3 Jul 2014 07:36:08 +0000 (15:36 +0800)
r=sgreen,a=sgreen

Bugzilla/Bug.pm
Bugzilla/Object.pm
Bugzilla/Template.pm

index cb132f31dab6d85e100502ebe3156eea16432ef8..b762a65003f0c681843888d55184982382662341 100644 (file)
@@ -504,6 +504,49 @@ sub preload {
     # If we don't do this, can_see_bug will do one call per bug in
     # the dependency and duplicate lists, in Bugzilla::Template::get_bug_link.
     $user->visible_bugs(\@all_dep_ids);
+
+    foreach my $bug (@$bugs) {
+        $bug->_preload_referenced_bugs();
+    }
+}
+
+# Helps load up bugs referenced in comments by retrieving them with a single
+# query from the database and injecting bug objects into the object-cache.
+sub _preload_referenced_bugs {
+    my $self = shift;
+    my @referenced_bug_ids;
+
+    # inject current duplicates into the object-cache first
+    foreach my $bug (@{ $self->duplicates }) {
+        $bug->object_cache_set()
+            unless Bugzilla::Bug->object_cache_get($bug->id);
+    }
+
+    # preload bugs from comments
+    require Bugzilla::Template;
+    foreach my $comment (@{ $self->comments }) {
+        if ($comment->type == CMT_HAS_DUPE || $comment->type == CMT_DUPE_OF) {
+            # duplicate bugs that aren't currently in $self->duplicates
+            push @referenced_bug_ids, $comment->extra_data
+                unless Bugzilla::Bug->object_cache_get($comment->extra_data);
+        }
+        else {
+            # bugs referenced in comments
+            Bugzilla::Template::quoteUrls($comment->body, undef, undef, undef,
+                sub {
+                    my $bug_id = $_[0];
+                    push @referenced_bug_ids, $bug_id
+                        unless Bugzilla::Bug->object_cache_get($bug_id);
+                });
+        }
+    }
+
+    # inject into object-cache
+    my $referenced_bugs = Bugzilla::Bug->new_from_list(
+        [ uniq @referenced_bug_ids ]);
+    foreach my $bug (@$referenced_bugs) {
+        $bug->object_cache_set();
+    }
 }
 
 sub possible_duplicates {
@@ -3879,10 +3922,23 @@ sub EmitDependList {
 # Creates a lot of bug objects in the same order as the input array.
 sub _bugs_in_order {
     my ($self, $bug_ids) = @_;
-    my $bugs = $self->new_from_list($bug_ids);
-    my %bug_map = map { $_->id => $_ } @$bugs;
-    my @result = map { $bug_map{$_} } @$bug_ids;
-    return \@result;
+    my %bug_map;
+    # there's no need to load bugs from the database if they are already in the
+    # object-cache
+    my @missing_ids;
+    foreach my $bug_id (@$bug_ids) {
+        if (my $bug = Bugzilla::Bug->object_cache_get($bug_id)) {
+            $bug_map{$bug_id} = $bug;
+        }
+        else {
+            push @missing_ids, $bug_id;
+        }
+    }
+    my $bugs = $self->new_from_list(\@missing_ids);
+    foreach my $bug (@$bugs) {
+        $bug_map{$bug->id} = $bug;
+    }
+    return [ map { $bug_map{$_} } @$bug_ids ];
 }
 
 # Get the activity of a bug, starting from $starttime (if given).
index e5704b3b15dec24adab02b53f9c16b2dbe3a401d..f2080363299081c6ff7bcbcdba14b54dddb8a4a1 100644 (file)
@@ -196,6 +196,23 @@ sub initialize {
 }
 
 # Provides a mechanism for objects to be cached in the request_cache
+
+sub object_cache_get {
+    my ($class, $id) = @_;
+    return $class->_object_cache_get(
+        { id => $id, cache => 1},
+        $class
+    );
+}
+
+sub object_cache_set {
+    my $self = shift;
+    return $self->_object_cache_set(
+        { id => $self->id, cache => 1 },
+        $self
+    );
+}
+
 sub _object_cache_get {
     my $class = shift;
     my ($param) = @_;
@@ -1446,6 +1463,58 @@ Returns C<1> if the passed-in value is true, C<0> otherwise.
 
 =back
 
+=head2 CACHE FUNCTIONS
+
+=over
+
+=item C<object_cache_get>
+
+=over
+
+=item B<Description>
+
+Class function which returns an object from the object-cache for the provided
+C<$id>.
+
+=item B<Params>
+
+Takes an integer C<$id> of the object to retrieve.
+
+=item B<Returns>
+
+Returns the object from the cache if found, otherwise returns C<undef>.
+
+=item B<Example>
+
+my $bug_from_cache = Bugzilla::Bug->object_cache_get(35);
+
+=back
+
+=item C<object_cache_set>
+
+=over
+
+=item B<Description>
+
+Object function which injects the object into the object-cache, using the
+object's C<id> as the key.
+
+=item B<Params>
+
+(none)
+
+=item B<Returns>
+
+(nothing)
+
+=item B<Example>
+
+$bug->object_cache_set();
+
+=back
+
+=back
+
 =head1 CLASS FUNCTIONS
 
 =over
index d1457a4fa2c5b78789eabb759cc07376031a0a13..8fe50fa4f8be8673445b903a370e1f7338b53b92 100644 (file)
@@ -147,9 +147,10 @@ sub get_format {
 # If you want to modify this routine, read the comments carefully
 
 sub quoteUrls {
-    my ($text, $bug, $comment, $user) = @_;
+    my ($text, $bug, $comment, $user, $bug_link_func) = @_;
     return $text unless $text;
     $user ||= Bugzilla->user;
+    $bug_link_func ||= \&get_bug_link;
 
     # We use /g for speed, but uris can have other things inside them
     # (http://foo/bug#3 for example). Filtering that out filters valid
@@ -203,7 +204,7 @@ sub quoteUrls {
         map { qr/$_/ } grep($_, Bugzilla->params->{'urlbase'}, 
                             Bugzilla->params->{'sslbase'})) . ')';
     $text =~ s~\b(${urlbase_re}\Qshow_bug.cgi?id=\E([0-9]+)(\#c([0-9]+))?)\b
-              ~($things[$count++] = get_bug_link($3, $1, { comment_num => $5, user => $user })) &&
+              ~($things[$count++] = $bug_link_func->($3, $1, { comment_num => $5, user => $user })) &&
                ("\x{FDD2}" . ($count-1) . "\x{FDD3}")
               ~egox;
 
@@ -250,7 +251,7 @@ sub quoteUrls {
     $text =~ s~\b($bug_re(?:$s*,?$s*$comment_re)?|$comment_re)
               ~ # We have several choices. $1 here is the link, and $2-4 are set
                 # depending on which part matched
-               (defined($2) ? get_bug_link($2, $1, { comment_num => $3, user => $user }) :
+               (defined($2) ? $bug_link_func->($2, $1, { comment_num => $3, user => $user }) :
                               "<a href=\"$current_bugurl#c$4\">$1</a>")
               ~egx;
 
@@ -266,7 +267,7 @@ sub quoteUrls {
         my $length = $+[0] - $-[0];
         my $match  = $1;
 
-        $match =~ s/((?:#$s*)?(\d+))/get_bug_link($2, $1);/eg;
+        $match =~ s/((?:#$s*)?(\d+))/$bug_link_func->($2, $1);/eg;
         # Replace the old string with the linkified one.
         substr($text, $offset, $length) = $match;
     }
@@ -289,7 +290,7 @@ sub quoteUrls {
     $text =~ s~(?<=^\*\*\*\ This\ bug\ has\ been\ marked\ as\ a\ duplicate\ of\ )
                (\d+)
                (?=\ \*\*\*\Z)
-              ~get_bug_link($1, $1, { user => $user })
+              ~$bug_link_func->($1, $1, { user => $user })
               ~egmx;
 
     # Now remove the encoding hacks in reverse order