--- lib/PXElator/CouchDB.pm 2009/08/12 19:49:36 205 +++ lib/PXElator/CouchDB.pm 2009/08/18 21:37:49 257 @@ -8,6 +8,11 @@ use LWP::UserAgent; use JSON; use Data::Dump qw/dump/; +use Time::HiRes qw/time/; +use Data::Structure::Util qw(unbless); +use Scalar::Util qw/blessed/; +use Storable qw/dclone/; +use Carp qw/carp/; sub new { my ($class, $host, $port, $options) = @_; @@ -56,29 +61,49 @@ our $rev; +sub rev { + my ($self,$url) = @_; + my $rev = $rev->{$url}; + $rev ||= eval { $self->get( $url )->{_rev} }; +# warn "# rev $url $rev"; + return $rev; +} + sub delete { my ($self, $url) = @_; - $self->request(DELETE => $url); + $self->request(DELETE => $url . '?rev=' . $self->rev($url) ); } sub get { my ($self, $url) = @_; - from_json $self->request(GET => $url); + JSON->new->utf8->decode( $self->request(GET => $url) ); } sub put { my ($self, $url, $json) = @_; - warn "put $url ",dump($json); - $rev->{$url} ||= eval { $self->get( $url )->{_rev} }; + $json->{_rev} = $rev->{$url} if defined $rev->{$url}; + + my $data = dclone $json; + $data = unbless $data if blessed $data; - $json->{_rev} = $rev->{$url} if $rev->{$url}; +# warn "# put ",dump( $data ); - $json = to_json $json if $json; + $json = JSON->new->utf8->encode( $data ); - $self->request(PUT => $url, $json); + carp "# put ",$json; + + do { + my $json = eval { $self->request(PUT => $url, $json) }; + if ( $@ ) { + $rev->{$url} = $self->rev( $url ); + warn "refresh rev $url = ", $rev->{$url}; + } else { + $rev->{$url} = JSON->new->decode( $json )->{rev}; + } + } until ! $@; } sub post { @@ -87,4 +112,37 @@ $self->request(POST => $url, $json); } +our $audit = __PACKAGE__->new; + +sub audit { + my $data = pop @_; + + my $url = join(' ', @_); + $url =~ s/\s+-\S+//g; # remove command line options + $url =~ s/\W+/-/g; + + my $time = $data->{time} = time(); + + my @caller_name = ( qw/package file line sub/ ); + my @caller = caller(0); + $caller[3] =~ s{^.+::}{}; # stip package name from sub + $data->{ $caller_name[$_] } = $caller[$_] foreach ( 0 .. $#caller_name ); + + my $caller; + my $depth = 0; + while ( my @c = caller($depth) ) { + push @$caller, [ splice(@c,0,4) ]; + $depth++; + } + + $data->{caller} = $caller; + +# carp 'audit ', dump($data); + + $time = int($time); # reduce granularity for url + my $package = $caller[0]; + $audit->put( "pxelator/$time.$package.$url", $data ); + +} + 1;