[Rt-commit] rt branch, 4.2/stop-calling-callbacks, created. rt-4.0.6-495-g32cac12

Ruslan Zakirov ruz at bestpractical.com
Mon Aug 27 16:54:25 EDT 2012


The branch, 4.2/stop-calling-callbacks has been created
        at  32cac1283c241fdacfc20dd73093acd647dcb51b (commit)

- Log -----------------------------------------------------------------
commit 32cac1283c241fdacfc20dd73093acd647dcb51b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Mar 7 18:24:33 2011 +0300

    first pass on stop calls from callbacks
    
    This experimental code that uses Sub::StopCalls
    module to jump over call to $m->callback method
    second time when we're sure there is no callback.
    
    Yes, we have a cache in the method, but code
    still does things before it gets to the cache
    check.
    
    The module rewrites perl program itself (op tree)
    to avoid any further calls from the current
    location. It's a bit extreme, but we may consider
    it with an option in the config.

diff --git a/lib/RT/Interface/Web/Request.pm b/lib/RT/Interface/Web/Request.pm
index d086511..ee03ff7 100644
--- a/lib/RT/Interface/Web/Request.pm
+++ b/lib/RT/Interface/Web/Request.pm
@@ -55,6 +55,7 @@ our $VERSION = '0.30';
 use HTML::Mason::PSGIHandler;
 use base qw(HTML::Mason::Request::PSGI);
 use Params::Validate qw(:all);
+use Sub::StopCalls;
 
 sub new {
     my $class = shift;
@@ -103,43 +104,54 @@ my %called = ();
 sub callback {
     my ($self, %args) = @_;
 
-    my $name = delete $args{'CallbackName'} || 'Default';
-    my $page = delete $args{'CallbackPage'} || $self->callers(0)->path;
+    my $page = delete $args{'CallbackPage'};
+    my $defined_page = !!$page;
+    $page ||= $self->callers(0)->path;
     unless ( $page ) {
         $RT::Logger->error("Couldn't get a page name for callbacks");
         return;
     }
 
-    my $CacheKey = "$page--$name";
-    return 1 if delete $args{'CallbackOnce'} && $called{ $CacheKey };
-    $called{ $CacheKey } = 1;
+    my $name = delete $args{'CallbackName'} || 'Default';
+    my $once = delete $args{'CallbackOnce'};
+    my $cache_key = "$page--$name";
+
+    return 1 if $once && $called{ $cache_key };
+    $called{ $cache_key } = 1;
 
-    my $callbacks = $cache{ $CacheKey };
-    unless ( $callbacks ) {
-        $callbacks = [];
+    my $callbacks;
+    unless ( exists $cache{ $cache_key } ) {
         my $path  = "/Callbacks/*$page/$name";
         my @roots = RT::Interface::Web->ComponentRoots;
         my %seen;
-        @$callbacks = (
+        $callbacks = [
             grep defined && length,
             # Skip backup files, files without a leading package name,
             # and files we've already seen
             grep !$seen{$_}++ && !m{/\.} && !m{~$} && m{^/Callbacks/[^/]+\Q$page/$name\E$},
             map { sort $self->interp->resolver->glob_path($path, $_) }
             @roots
-        );
+        ];
         foreach my $comp (keys %seen) {
             next unless $seen{$comp} > 1;
             $RT::Logger->error("Found more than one occurrence of the $comp callback.  This may cause only one of the callbacks to run.  Look for the duplicate Callback in your @roots");
         }
+        $callbacks = undef unless @$callbacks;
 
-        $cache{ $CacheKey } = $callbacks unless RT->Config->Get('DevelMode');
+        $cache{ $cache_key } = $callbacks unless RT->Config->Get('DevelMode');
+    } else {
+        $callbacks = $cache{ $cache_key };
+    }
+    unless ( $callbacks ) {
+        return Sub::StopCalls::stop() unless $defined_page;
+        return;
     }
 
     my @rv;
     foreach my $cb ( @$callbacks ) {
         push @rv, scalar $self->comp( $cb, %args );
     }
+    return Sub::StopCalls::stop(@rv) if $once && !$defined_page;
     return @rv;
 }
 }

-----------------------------------------------------------------------


More information about the Rt-commit mailing list