added lf2p filter and use it to format abstracts
[angular-mojolicious.git] / couchdb-trigger.pl
index 5f02e0f..1724b67 100755 (executable)
@@ -1,6 +1,14 @@
 #!/usr/bin/perl
 
+# back-end trigger server for CouchDB monitoring changes feed:
+#
 # http://wiki.apache.org/couchdb/HTTP_database_API#Changes
+#
+# implements state machine using document which you cen put with:
+#
+# curl -X PUT http://localhost:5984/monitor/df -d '{"trigger":{"command":"df -P","format":"table"}}'
+#
+# DEFAULT TRIGGER EXECUTE SHELL COMMANDS. IT IS NOT SECURE IF YOUR COUCHDB ISN'T SECURE!
 
 use warnings;
 use strict;
@@ -9,8 +17,19 @@ use lib 'common/mojo/lib';
 
 use Mojo::Client;
 use Mojo::JSON;
+use Time::HiRes qw(time);
+use Data::Dump qw(dump);
+
+my ( $url, $trigger_path ) = @ARGV;
+
+$url          ||= 'http://localhost:5984/monitor';
+$trigger_path ||= 'trigger/shell.pm' ;
+
+our $database = $1 if $url =~ m{/(\w+)/?$};
+
+sub commit { warn "# commit ignored\n"; }
+require $trigger_path if -e $trigger_path;
 
-my $url = 'http://localhost:5984/monitor';
 my $seq = 0;
 
 my $client = Mojo::Client->new;
@@ -29,12 +48,9 @@ while( ! $error ) {
        $tx->res->body(sub{
                my ( $content, $body ) = @_;
 
-               debug 'BODY' => $body;
+               return if length($body) == 0; # empty chunk, heartbeat?
 
-               if ( length($body) == 0 ) {
-                       warn "# empty chunk, heartbeat?\n";
-                       return;
-               }
+               debug 'BODY' => $body;
 
                foreach ( split(/\r?\n/, $body) ) { # we can get multiple documents in one chunk
 
@@ -54,11 +70,11 @@ while( ! $error ) {
 
                                debug 'change' => $change;
 
-                               if ( my $trigger = $change->{doc}->{trigger} ) {
-                                       if ( exists $trigger->{active} ) {
+                               if ( filter($change) ) {
+                                       if ( exists $change->{doc}->{trigger}->{active} ) {
                                                debug 'trigger.active',  $change->{doc}->{trigger}->{active};
                                        } else {
-                                               $trigger->{active} = [ time() ];
+                                               $change->{doc}->{trigger}->{active} = [ time() ];
 
                                                debug 'TRIGGER start PUT ', $change->{doc};
                                                $client->put( "$url/$id" => $json->encode( $change->{doc} ) => sub {
@@ -67,21 +83,21 @@ while( ! $error ) {
                                                                if ( $tx->res->code == 409 ) {
                                                                        info "TRIGGER ABORTED started on another worker? ", $tx->error;
                                                                } else {
-                                                                       info "ERROR ", $tx->error;
+                                                                       info "ERROR $url/$id ", $tx->error;
                                                                }
                                                        } else {
                                                                my $res = $tx->res->json;
                                                                $change->{doc}->{_rev} = $res->{rev};
-                                                               debug "TRIGGER execute ", $change->{doc};
 
-                                                               # FIXME trigger logic?
+                                                               debug "TRIGGER execute ", $change->{doc};
+                                                               trigger( $change );
 
-                                                               push @{ $trigger->{active} }, time(); # timestamp step
+                                                               push @{ $change->{doc}->{trigger}->{active} }, time(), 0; # last timestamp
 
                                                                $client->put( "$url/$id" => $json->encode( $change->{doc} ) => sub {
                                                                        my ($client,$tx) = @_;
                                                                        if ($tx->error) {
-                                                                               info "ERROR", $tx->error;
+                                                                               info "ERROR $url/$id", $tx->error;
                                                                        } else {
                                                                                my $res = $tx->res->json;
                                                                                $change->{doc}->{_rev} = $res->{rev};
@@ -98,6 +114,8 @@ while( ! $error ) {
 
                }
 
+               commit;
+
        });
        $client->start($tx);