[Bps-public-commit] r14435 - in Pushmi/trunk: . Pushmi-Admin/etc Pushmi-Admin/lib/Pushmi/Admin Pushmi-Admin/lib/Pushmi/Admin/Event Pushmi-Admin/lib/Pushmi/Admin/Model Pushmi-Admin/share/web/static/css

alexmv at bestpractical.com alexmv at bestpractical.com
Wed Jul 23 13:27:10 EDT 2008


Author: alexmv
Date: Wed Jul 23 13:27:10 2008
New Revision: 14435

Added:
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Event/
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Event/ReplicaStatus.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Watcher.pm
Modified:
   Pushmi/trunk/   (props changed)
   Pushmi/trunk/Pushmi-Admin/etc/config.yml
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Dispatcher.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Model/Replica.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/View.pm
   Pushmi/trunk/Pushmi-Admin/share/web/static/css/app.css

Log:
 r34565 at kohr-ah:  chmrr | 2008-07-23 13:26:58 -0400
  * PubSub is almost working


Modified: Pushmi/trunk/Pushmi-Admin/etc/config.yml
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/etc/config.yml	(original)
+++ Pushmi/trunk/Pushmi-Admin/etc/config.yml	Wed Jul 23 13:27:10 2008
@@ -12,7 +12,7 @@
     Driver: SQLite
     Host: localhost
     Password: ''
-    RecordBaseClass: Jifty::DBI::Record::Cachable
+    RecordBaseClass: Jifty::DBI::Record::Memcached
     User: ''
     Version: 0.0.1
   DevelMode: 1
@@ -31,7 +31,7 @@
     - AdminUI: {}
   PubSub: 
     Backend: Memcached
-    Enable: ~
+    Enable: 1
   SkipAccessControl: 0
   TemplateClass: Pushmi::Admin::View
   View: 
@@ -51,6 +51,7 @@
       error_mode: fatal
     Port: 8888
     ServeStaticFiles: 1
+    ServerClass: Jifty::Server::Fork
     StaticRoot: share/web/static
     TemplateRoot: share/web/templates
 application:

Added: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin.pm
==============================================================================
--- (empty file)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin.pm	Wed Jul 23 13:27:10 2008
@@ -0,0 +1,60 @@
+use warnings;
+use strict;
+
+package Pushmi::Admin;
+
+sub svn_info_for {
+    my $class = shift;
+    my ($url) = @_;
+
+    my $memcached = $Jifty::DBI::Record::Memcached::MEMCACHED;
+    my $props = $memcached->get( $url );
+    return $props if defined $props;
+
+    my $client = SVN::Client->new(
+        auth => [
+            SVN::Client::get_simple_provider(),
+            SVN::Client::get_username_provider(),
+        ]
+    );
+
+    my $start = Time::HiRes::time;
+    local $SIG{ALRM} = sub { die "Timeout!" };
+    alarm 10;
+    eval {
+        $client->info(
+            $url, undef, "HEAD",
+            sub {
+                $props->{rev}  = $_[1]->rev;
+                $props->{date} = $_[1]->last_changed_date;
+            },
+            0
+        );
+    };
+    warn "$@" if $@;
+    alarm 0;
+
+    my $for;
+    if ($props) {
+        $props->{latency} = Time::HiRes::time - $start;
+        $for = $props->{latency} * 5;
+        $for = 2 if $for < 2;
+    } else {
+        $props = '';
+        $for = 5;
+    }
+    $for *= 60 unless $url =~ /^file:/;
+    $memcached->set( $url => $props, $for );
+    
+    return $props;
+}
+
+sub clear_svn_info_for {
+    my $class = shift;
+    my ($url) = @_;
+
+    my $memcached = $Jifty::DBI::Record::Memcached::MEMCACHED;
+    $memcached->delete( $url );
+}
+
+1;

Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Dispatcher.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Dispatcher.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Dispatcher.pm	Wed Jul 23 13:27:10 2008
@@ -5,7 +5,6 @@
 use Jifty::Dispatcher -base;
 
 on '/create' => run {
-    warn YAML::Dump( Jifty->web->response );
     if (    Jifty->web->response->result("create")
         and Jifty->web->response->result("create")->success )
     {
@@ -33,9 +32,4 @@
     show '/advanced';
 };
 
-after '*' => run {
-    return if already_run;
-    Pushmi::Admin::Model::Replica->clear_cache;
-};
-
 1;

Added: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Event/ReplicaStatus.pm
==============================================================================
--- (empty file)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Event/ReplicaStatus.pm	Wed Jul 23 13:27:10 2008
@@ -0,0 +1,18 @@
+package Pushmi::Admin::Event::ReplicaStatus;
+use strict;
+use warnings;
+use base 'Pushmi::Admin::Event';
+
+sub match {
+    my $self    = shift;
+    my $query   = shift;
+
+    return $self->data->{id} == $query->{id} if $query->{id};
+    return 1;
+}
+
+sub render_arguments {
+    %{$_[0]->data};
+}
+
+1;

Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Model/Replica.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Model/Replica.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Model/Replica.pm	Wed Jul 23 13:27:10 2008
@@ -92,11 +92,16 @@
 
 sub pushmi {
     my $self = shift;
-    return Pushmi::Mirror->new( path => $self->svn_root );
+    return $self->{pushmi} if $self->{pushmi};
+    my $p = Pushmi::Mirror->new( path => $self->svn_root );
+    eval { $p->repos } or return;
+    return $self->{pushmi} = $p;
 }
 
 sub delete {
     my $self = shift;
+    $self->stop_watcher;
+    $self->clear_cache;
     my $http = Pushmi::Admin::Model::HttpRootCollection->new;
     $http->limit( column => "replica_id", value => $self->id );
     $_->delete while $_ = $http->next;
@@ -114,113 +119,92 @@
 
 sub sync {
     my $self = shift;
-    return if $self->pushmi->locked;
+    return if $self->pushmi and $self->pushmi->locked;
 
     unless (fork) {
+        close STDOUT; # XXX This doesn't work?
         exec( $^X, Jifty->config->app("pushmi_bin"), "sync",
             $self->svn_root );
     }
+    $self->clear_cache;
 }
 
-sub svn_info_for {
+sub svn_root {
+    my $self  = shift;
+    my @parts = File::Spec->splitpath( Jifty->config->app('svn_root') );
+    return File::Spec->catfile( @parts, $self->clean_name );
+}
+
+sub cache {
     my $self = shift;
-    my ($url) = @_;
+    return $self->{cache} if $self->{cache};
+    return {} unless $self->id;
 
-    my $client = SVN::Client->new(
-        auth => [
-            SVN::Client::get_simple_provider(),
-            SVN::Client::get_username_provider(),
-        ]
-    );
+    my $c      = {};
+    my $local  = Pushmi::Admin->svn_info_for( "file://" . $self->svn_root );
+    my $remote = Pushmi::Admin->svn_info_for( $self->url );
+    if ( not $local or not $self->pushmi ) {
+        $self->set_status("failed");
+    } elsif ( not $remote ) {
+        $c->{local_revision} = $local->{rev};
+        $c->{local_date}     = $local->{date};
+        $self->set_status("offline");
+    } else {
+        $c->{remote_revision} = $remote->{rev};
+        $c->{remote_date}     = $remote->{date};
+        $c->{latency}         = $remote->{latency};
+        $c->{local_revision}  = $local->{rev};
+        $c->{local_date}      = $local->{date};
+        if ( $self->pushmi->locked ) {
+            $self->set_status("loading");
+        } elsif ( $local->{rev} < $remote->{rev} ) {
+            $self->set_status("behind");
+        } else {
+            $self->set_status("ok");
+        }
+    }
+    $c->{status} = $self->_value("status");
+    return $self->{cache} = $c;
+}
 
-    my $start = Time::HiRes::time;
-    my $props;
-    local $SIG{ALRM} = sub { die "Timeout!" };
-    alarm 10;
-    eval {
-        $client->info(
-            $url, undef, "HEAD",
-            sub {
-                $props->{rev}  = $_[1]->rev;
-                $props->{date} = $_[1]->last_changed_date;
-            },
-            0
-        );
-    };
-    warn "$@" if $@;
-    alarm 0;
-    $props->{latency} = Time::HiRes::time - $start if $props;
-    return $props;
+sub clear_cache {
+    my $self = shift;
+    delete $self->{cache};
+    Pushmi::Admin->clear_svn_info_for( "file://" . $self->svn_root );
+    Pushmi::Admin->clear_svn_info_for( $self->url );
 }
 
 sub remote_revision {
     my $self = shift;
-    $self->status;
-    return $CACHE{ $self->id }{remote_revision};
+    return $self->cache->{remote_revision};
 }
 
 sub latency {
     my $self = shift;
-    $self->status;
-    return sprintf( "%.2f seconds", $CACHE{ $self->id }{latency} );
+    return sprintf( "%.2f seconds", $self->cache->{latency} );
 }
 
 sub last_remote {
     my $self = shift;
-    $self->status;
     return Time::Duration::duration(
-        time - $CACHE{ $self->id }{remote_date} / 1e6 )
+        time - $self->cache->{remote_date} / 1e6 )
         . " ago";
 }
 
 sub local_revision {
     my $self = shift;
-    $self->status;
-    return $CACHE{ $self->id }{local_revision};
+    return $self->cache->{local_revision};
 }
 
 sub last_local {
     my $self = shift;
-    $self->status;
-    return Time::Duration::duration(
-        time - $CACHE{ $self->id }{local_date} / 1e6 )
+    return Time::Duration::duration( time - $self->cache->{local_date} / 1e6 )
         . " ago";
 }
 
-sub svn_root {
-    my $self  = shift;
-    my @parts = File::Spec->splitpath( Jifty->config->app('svn_root') );
-    return File::Spec->catfile( @parts, $self->clean_name );
-}
-
 sub status {
     my $self = shift;
-    if ( $self->id and not $CACHE{ $self->id } ) {
-        my $c = $CACHE{ $self->id } = {};
-        my $local  = $self->svn_info_for( "file://" . $self->svn_root );
-        my $remote = $self->svn_info_for( $self->url );
-        if ( not $local ) {
-            $self->set_status("failed");
-        } elsif ( not $remote ) {
-            $c->{local_revision} = $local->{rev};
-            $c->{local_date}     = $local->{date};
-            $self->set_status("offline");
-        } else {
-            $c->{remote_revision} = $remote->{rev};
-            $c->{remote_date}     = $remote->{date};
-            $c->{latency}         = $remote->{latency};
-            $c->{local_revision}  = $local->{rev};
-            $c->{local_date}      = $local->{date};
-            if ( $self->pushmi->locked ) {
-                $self->set_status("loading");
-            } elsif ( $local->{rev} < $remote->{rev} ) {
-                $self->set_status("behind");
-            } else {
-                $self->set_status("ok");
-            }
-        }
-    }
-    return $self->_value("status");
+    return $self->cache->{status};
 }
 
 sub long_status {
@@ -251,12 +235,42 @@
     }
 }
 
-sub current_user_can {
-    return 1;
+sub start_watcher {
+    my $self = shift;
+    $SIG{CHLD} = sub { print STDERR "sigchld: $!" while wait > 0; };
+    Jifty->bus->modify(
+        watchers => sub {
+            return
+                if $_->{ $self->clean_name }
+                and kill 0, $_->{ $self->clean_name }{pid};
+            if ( my $pid = fork ) {
+                $_->{ $self->clean_name } = { pid => $pid };
+            } else {
+                my $id = $self->id;
+                exec( $^X => "-Ilib",
+                    "-MPushmi::Admin::Watcher",
+                    "-e" => "Pushmi::Admin::Watcher->new($id)"
+                );
+            }
+        }
+    );
 }
 
-sub clear_cache {
-    %CACHE = ();
+sub stop_watcher {
+    my $self = shift;
+    my $pid;
+    Jifty->bus->modify(
+        watchers => sub {
+            return unless $_->{ $self->clean_name };
+            $pid = $_->{ $self->clean_name }{pid};
+            delete $_->{ $self->clean_name };
+        }
+    );
+    kill 2, $pid if $pid;
+}
+
+sub current_user_can {
+    return 1;
 }
 
 1;

Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/View.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/View.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/View.pm	Wed Jul 23 13:27:10 2008
@@ -1,5 +1,8 @@
 package Pushmi::Admin::View;
 
+use strict;
+use warnings;
+
 use Jifty::View::Declare -base;
 
 use YAML;
@@ -13,20 +16,11 @@
         { id is 'replica_list', class is 'roundbox' };
         h2 {"Current replicas"};
         while ( my $replica = $replicas->next ) {
-            div {
-                { class is 'replica status-light ' . $replica->status };
-                h3 {
-                    hyperlink(
-                        url   => "/replica/" . $replica->clean_name,
-                        label => $replica->name
-                    );
-                };
-                hyperlink( url => $replica->url, label => $replica->url );
-                div {
-                    { class is 'status' }
-                    $replica->long_status;
-                }
-            }
+            render_region(
+                name      => "summary-" . $replica->id,
+                path      => "/fragments/summary",
+                arguments => { id => $replica->id }
+            );
         }
     };
 
@@ -96,26 +90,46 @@
     }
 }
 
+template 'fragments/summary' => sub {
+    my $id = get('id');
+    my $replica = Pushmi::Admin::Model::Replica->load($id);
+    div {
+        { class is 'replica status-light ' . $replica->status };
+        h3 {
+            hyperlink(
+                url   => "/replica/" . $replica->clean_name,
+                label => $replica->name
+            );
+        };
+        hyperlink( url => $replica->url, label => $replica->url );
+        div {
+            { class is 'status' }
+            $replica->long_status;
+        }
+    };
+
+    # Add a PubSub watcher, if need be
+    Jifty->subs->add(
+        class       => 'ReplicaStatus',
+        queries     => [{ id => $id }],
+        mode        => 'Replace',
+        region      => Jifty->web->qualified_region,
+        render_with => '/fragments/summary',
+    );
+    $replica->start_watcher;
+};
+
 template 'replica' => page { title => "About " . get("replica")->name }
     content {
     my $replica = get 'replica';
     div {
         { class is 'roundbox' };
-        h2 {"Replica status"}
-        div {
-            { class is 'replica status-light ' . $replica->status };
-            h3 {
-                hyperlink(
-                    url   => "/replica/" . $replica->clean_name,
-                    label => $replica->name
-                );
-            };
-            hyperlink( url => $replica->url, label => $replica->url );
-            div {
-                { class is 'status' }
-                $replica->long_status;
-            }
-        }
+        h2 {"Replica status"};
+        render_region(
+            name      => "summary-" . $replica->id,
+            path      => "/fragments/summary",
+            arguments => { id => $replica->id }
+        );
     };
 
     div {
@@ -164,6 +178,7 @@
             h2 {"Local replica failure"};
         }
     };
+
     div {
         { id is 'advanced' }
         hyperlink(

Added: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Watcher.pm
==============================================================================
--- (empty file)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Watcher.pm	Wed Jul 23 13:27:10 2008
@@ -0,0 +1,44 @@
+package Pushmi::Admin::Watcher;
+
+use Jifty;
+
+use strict;
+use warnings;
+
+BEGIN {
+    # We must close STDOUT, or our parent request may never return to the client
+    close STDOUT;
+    Jifty->new;
+}
+    
+
+sub new {
+    my ($class, $id) = @_;
+    my $previous = "";
+
+    my $replica = Pushmi::Admin::Model::Replica->load($id);
+    exit unless $replica->id;
+
+    Jifty->bus->modify(
+        watchers => sub {
+            $_->{ $replica->clean_name }{pid} = $$;
+        }
+    );
+    while (1) {
+        $replica = Pushmi::Admin::Model::Replica->load($id);
+        last unless $replica->id;
+        if ($replica->long_status ne $previous) {
+            print STDERR "@{[$replica->clean_name]}: NEW STATUS: @{[$replica->long_status]}\n";
+            Pushmi::Admin::Event::ReplicaStatus->new(
+                { id => $id }
+            )->publish;
+        }
+        $previous = $replica->long_status;
+        sleep 1;
+    }
+    
+    print STDERR "@{[$id]} exiting\n";
+    exit;
+}
+
+1;

Modified: Pushmi/trunk/Pushmi-Admin/share/web/static/css/app.css
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/share/web/static/css/app.css	(original)
+++ Pushmi/trunk/Pushmi-Admin/share/web/static/css/app.css	Wed Jul 23 13:27:10 2008
@@ -82,6 +82,7 @@
   font-weight: normal;
 }
 
+
 /* Rounded boxes and titles */
 
 .roundbox {
@@ -108,15 +109,21 @@
   clear: left;
 }
 
-/* Customizations */
+
+/* Replica summaries, lists, and status lights */
+
 #replica_status {
-  width: 450px;
   background: #223;
 }
 
+.replica + .replica {
+  border-top: 1px solid #334;
+}
+
 .replica {
   clear: left;
   padding-left: 60px;
+  margin: 1em 0;
 }
 
 .replica.status-light { 
@@ -130,6 +137,9 @@
 .status-light.offline { background-image: url(/static/images/status/red.png);    }
 .status-light.failed  { background-image: url(/static/images/status/red.png);    }
 
+
+/* The "advanced" button and page */
+
 #advanced {
   margin: 1em 0;
   padding: 1em;
@@ -142,12 +152,15 @@
   padding: 1em;
 }
 
-.delete_replica input, .remirror_replica input {
+input.button {
   border: 1px solid #334;
   background: #223;
   color: #ddd;
   -moz-border-radius: 5px; -webkit-border-radius: 5px;
   padding: 0.5em;
+}
+
+.delete_replica input, .remirror_replica input {
   padding-left: 2.5em;
   background-repeat: no-repeat;
   background-position: 10px 7px;
@@ -164,4 +177,7 @@
 
 .delete_replica {
   border-bottom: 1px solid #334;
-}
\ No newline at end of file
+}
+
+
+/* */
\ No newline at end of file



More information about the Bps-public-commit mailing list