every_foo for Takfile, add Tak->await_all
Matt S Trout [Fri, 11 Nov 2011 10:15:01 +0000 (10:15 +0000)]
lib/Tak.pm
lib/Tak/Request.pm
lib/Tak/Script.pm

index 33bc378..1e0de48 100644 (file)
@@ -14,4 +14,22 @@ sub loop_until {
   $loop->loop_once until $_[1];
 }
 
+sub await_all {
+  my ($class, @requests) = @_;
+  @requests = grep !$_->is_done, @requests;
+  return unless @requests;
+  my %req = map +("$_" => "$_"), @requests;
+  my $done;
+  my %orig;
+  my %on_r = map {
+    my $orig = $orig{$_} = $_->{on_result};
+    my $tag = $req{$_};
+    ($_ => sub { delete $req{$tag}; $orig->(@_); $done = 1 unless keys %req; })
+  } @requests;
+  $_->{on_result} = $on_r{$_} for @requests;
+  $class->loop_until($done);
+  $_->{on_result} = $orig{$_} for @requests;
+  return;
+}
+
 1;
index 49731d9..abb5ad5 100644 (file)
@@ -7,6 +7,8 @@ has on_progress => (is => 'ro');
 
 has on_result => (is => 'ro', required => 1);
 
+has is_done => (is => 'rw', default => sub { 0 });
+
 sub progress {
   my ($self, @report) = @_;
   if (my $cb = $self->on_progress) {
@@ -16,6 +18,7 @@ sub progress {
 
 sub result {
   my ($self, $type, @data) = @_;
+  $self->is_done(1);
   $self->on_result->(Tak::Result->new(type => $type, data => \@data));
 }
 
index b932fea..00208d2 100644 (file)
@@ -80,6 +80,8 @@ sub run {
     return $self->_run($cmd, $code, @argv);
   } elsif ($code = $self->can("each_$cmd")) {
     return $self->_run_each($cmd, $code, @argv);
+  } elsif ($code = $self->can("every_$cmd")) {
+    return $self->_run_every($cmd, $code, @argv);
   }
   $self->stderr->print("No such command: ${cmd}\n");
   return $self->local_help;
@@ -118,9 +120,6 @@ sub _run_each {
     return;
   }
   my $opt = $self->_maybe_parse_options($code, \@argv);
-  if (my $prepare = $self->can("prepare_$cmd")) {
-    $self->$prepare($opt, @argv);
-  }
   $self->local_client->ensure(connector => 'Tak::ConnectorService');
   foreach my $target (@targets) {
     my $remote = $self->_connection_to($target);
@@ -128,6 +127,19 @@ sub _run_each {
   }
 }
 
+sub _run_every {
+  my ($self, $cmd, $code, @argv) = @_;
+  my @targets = $self->_host_list_for($cmd);
+  unless (@targets) {
+    $self->stderr->print("No targets for ${cmd}\n");
+    return;
+  }
+  my $opt = $self->_maybe_parse_options($code, \@argv);
+  $self->local_client->ensure(connector => 'Tak::ConnectorService');
+  my @remotes = map $self->_connection_to($_), @targets;
+  $self->$code(\@remotes, $opt, @argv);
+}
+
 sub _host_list_for {
   my ($self, $command) = @_;
   my @host_spec = map split(' ', $_), @{$self->options->{host}};