AnyEvent-CouchDB

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

UNRELEASED
  * see if we can load new attachment data asynchronously.
  * write more tests
  * need to improve startkey/endkey/key JSON encoding.

1.31 2013-06-05
  - merged Maroun NAJM's patch for bulk_doc properties
    http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API#Transactional_Semantics_with_Bulk_Updates

1.30
  - finally fixed that annoying connection timeout problem (thanks to Walter Werner)

Changes  view on Meta::CPAN

  - stream module lacked functionality to prevent socket closing.
    closes RT #71601 (by http://benbot.myopenid.com (Mike Zedeler?))

1.27 2011-09-01
  - added a workaround for a strange bug in
    AnyEvent::CouchDB::Stream where strange characters
    would appear in between JSON objects in the stream.
  - added more people to the credits

1.26 2011-08-29
  - RT#70506 save_doc doesn't update attachment stubs
  - RT#70480 open_doc(undef) returns db status
  - RT#70425 AnyEvent::CouchDB::Stream enhancement

1.25 2011-07-13
  - support for https couches (by Luke Closs)

1.24 2011-04-13
  - various fixes to $db->view 
    (thanks to Matt Adams for the patch and Ryan Perry for the bug reports)

Changes  view on Meta::CPAN

  - $db->view passes authentication information

1.22 2010-10-12
  - Reverted a change to the exception code that serialized the exception data to JSON.

1.21 2010-09-13
  - Had some problems with PAUSE.  Same as 1.20.  Reuploading.

1.20 2010-05-13
  - a double-utf8 bug was fixed (by Stéphane)
  - fetch attachments using open_attachment(). (by Michael Zedeler)

1.19 2010-05-06
  - AnyEvent::CouchDB::Stream !!! (by franckcuny)

1.18 2010-04-15
  - encode the exception message as json (by franckcuny)

1.17 2010-03-26
  - support to continuous replication, close RT #54922 (by franckcuny)

Changes  view on Meta::CPAN

    how the $query function deals with the 'group' parameter.
    It now translates between Perl's notion of truth to Javascript's
    formal true/false values implicitly.
  - added eg/pager example (by Jan-Felix Wittmann)

1.03 2008-10-10
  - added method for getting a server's config
  - applied patch to $query from Jan-Felix Wittmann

1.02 2008-09-15
  - added documentation for attach and detatch
  - added document length to new attachment stubs

1.01 2008-09-14
  - add support for attachments
  - mention DB::CouchDB in POD

1.00 2008-07-25
  - initial release

MANIFEST  view on Meta::CPAN

eg/replicate.pl
lib/AnyEvent/CouchDB.pm
lib/AnyEvent/CouchDB/Database.pm
lib/AnyEvent/CouchDB/Exceptions.pm
lib/AnyEvent/CouchDB/Stream.pm
Makefile.PL
MANIFEST			This list of files
MANIFEST.SKIP
README
t/00_basic.t
t/10_attachments.t
META.yml                                 Module meta-data (added by MakeMaker)

lib/AnyEvent/CouchDB/Database.pm  view on Meta::CPAN

    headers => $self->_build_headers($options),
    body    => $self->json( { "keys" => $doc_ids } ),
    $cb
  );
  $cv;
}

sub save_doc {
  my ( $self, $doc, $options ) = @_;

  # create attachment stubs for new inlined attachments
  my $_attachments = sub {
    my ( $doc ) = @_;
    my $_a = $doc->{_attachments};
    return unless defined $_a;
    my $revpos = $doc->{_rev};
    $revpos =~ s/-.*$//;
    for my $key (keys %$_a) {
      if ( exists($_a->{$key}{data}) ) {
        my $file = $_a->{$key};
        $file->{length} = length(decode_base64($file->{data}));
        $file->{revpos} = $revpos;
        $file->{stub}   = JSON::true();
        delete $file->{data};

lib/AnyEvent/CouchDB/Database.pm  view on Meta::CPAN

    }
  };

  if ( $options->{success} ) {
    my $orig = $options->{success};
    $options->{success} = sub {
      my ($resp) = @_;
      $orig->($resp);
      $doc->{_id}  = $resp->{id};
      $doc->{_rev} = $resp->{rev};
      $_attachments->($doc);
    };
  }
  else {
    $options->{success} = sub {
      my ($resp) = @_;
      $doc->{_id}  = $resp->{id};
      $doc->{_rev} = $resp->{rev};
      $_attachments->($doc);
    };
  }
  my ( $cv, $cb ) = cvcb( $options, 201, $self->json_encoder );
  my ( $method, $uri );
  if ( not defined $doc->{_id} ) {
    $method = 'POST';
    $uri    = $self->uri;
  }
  else {
    $method = 'PUT';

lib/AnyEvent/CouchDB/Database.pm  view on Meta::CPAN

  http_request(
    DELETE => $self->uri
        . uri_escape_utf8( $doc->{_id} )
        . $query->( { rev => $doc->{_rev} } ),
    headers => $self->_build_headers($options),
    $cb
  );
  $cv;
}

sub attach {
  my ( $self, $doc, $attachment, $options ) = @_;
  my $body < io( $options->{src} );
  my $length = length($body);
  $options->{type} ||= 'text/plain';
  if ( $options->{success} ) {
    my $orig = $options->{success};
    $options->{success} = sub {
      my ($resp) = @_;
      $orig->($resp);
      $doc->{_id}  = $resp->{id};
      $doc->{_rev} = $resp->{rev};
      $doc->{_attachments} ||= {};
      $doc->{_attachments}->{$attachment} = {
        'content_type' => $options->{type},
        'length'       => $length,
        'stub'         => JSON::true,
      };
    };
  }
  else {
    $options->{success} = sub {
      my ($resp) = @_;
      $doc->{_id}  = $resp->{id};
      $doc->{_rev} = $resp->{rev};
      $doc->{_attachments} ||= {};
      $doc->{_attachments}->{$attachment} = {
        'content_type' => $options->{type},
        'length'       => $length,
        'stub'         => JSON::true,
      };
    };
  }
  my ( $cv, $cb ) = cvcb( $options, 201, $self->json_encoder );
  http_request(
    PUT => $self->uri
        . uri_escape_utf8( $doc->{_id} ) . "/"
        . uri_escape_utf8($attachment)
        . $query->( { rev => $doc->{_rev} } ),
    headers => $self->_build_headers($options),
    body    => $body,
    $cb
  );
  $cv;
}

sub open_attachment {
  my ( $self, $doc, $attachment, $options ) = @_;
  my $cv = AnyEvent->condvar;

  # passthrough handler without json encoding
  my $success = sub {
    $options->{success}->(@_) if ($options->{success});
    $cv->send(@_);
  };

  # error handler that croaks with http headers
  my $error = sub {

lib/AnyEvent/CouchDB/Database.pm  view on Meta::CPAN

    if ($headers->{Status} >= 200 and $headers->{Status} < 400) {
      $success->(@_);
    } else {
      $error->($headers);
    }
  };

  http_request(
    GET => $self->uri
        . uri_escape_utf8( $doc->{_id} ) . "/"
        . uri_escape_utf8($attachment),
    headers => $self->_build_headers($options),
    $cb
  );
  $cv;
}

sub detach {
  my ( $self, $doc, $attachment, $options ) = @_;
  if ( $options->{success} ) {
    my $orig = $options->{success};
    $options->{success} = sub {
      my ($resp) = @_;
      $orig->($resp);
      $doc->{_id}  = $resp->{id};
      $doc->{_rev} = $resp->{rev};
      delete $doc->{_attachments}->{$attachment};
    };
  }
  else {
    $options->{success} = sub {
      my ($resp) = @_;
      $doc->{_id}  = $resp->{id};
      $doc->{_rev} = $resp->{rev};
      delete $doc->{_attachments}->{$attachment};
    };
  }
  my ( $cv, $cb ) = cvcb( $options, undef, $self->json_encoder );
  http_request(
    DELETE => $self->uri
        . uri_escape_utf8( $doc->{_id} ) . "/"
        . uri_escape_utf8($attachment)
        . $query->( { rev => $doc->{_rev} } ),
    headers => $self->_build_headers($options),
    $cb
  );
  $cv;
}

sub bulk_docs {
  my ( $self, $docs, $options ) = @_;
  my ( $cv, $cb ) = cvcb( $options, undef, $self->json_encoder );

lib/AnyEvent/CouchDB/Database.pm  view on Meta::CPAN

existing CouchDB document.  It returns a condvar.

Note that upon success, C<$doc> will have its C<_id> and C<_rev> keys
updated.  This allows you to save C<$doc> repeatedly using the same hashref.

=head3 $cv = $db->remove_doc($doc, [ \%options ])

This method is used to remove a document from the database, and it returns a
condvar.

=head3 $cv = $db->attach($doc, $attachment, \%options)

This method adds an attachment to a document, and it returns a condvar.  Note
that the C<%options> are NOT optional for this method.  You must provide a
C<src> for the data which should be a path that can be understood by
L<IO::All>.  You must also provide a MIME content C<type> for this data.  If
none is provided, it'll default to C<text/plain>.

B<Example>:

  $db->attach($doc, "issue.net", {
    src  => '/etc/issue.net',
    type => 'text/plain'
  })->recv;

=head3 $cv = $db->detach($doc, $attachment, [ \%options ])

This method removes an attachment from a document, and it returns a condvar.

B<Example>:

  $db->detach($doc, "issue.net")->recv;

=head3 $cv = $db->open_attachment($doc, $attachment)

This method retrieves an attachment and returns the contents as a condvar.

B<Example>:

  my($body, $headers) = $db->open_attachment($doc, "issue.net")->recv;
  my $content_type    = $headers->{'content-type'};

=head3 $cv = $db->bulk_docs(\@docs, [ \%options ])

This method requests that many create, update, and delete operations be
performed in one shot.  You pass it an arrayref of documents, and it'll
return a condvar.

=head2 Database Queries

t/10_attachments.t  view on Meta::CPAN

my $sg = Scope::Guard->new(
  $ENV{COUCHDB_KEEP_DB} ? 
      sub { diag "Database kept. Name: ", $db->name }
  :   sub { $db->drop->recv }
);
$db->create->recv;

{
  my $doc = { _id => 'my_doc' };
  ok($db->save_doc($doc)->recv, 'Create test doc.');
  ok($db->attach($doc, 'testscript.pl', { src => $0, type => 'text/html' })->recv, 'Attach this script to doc.');
  my $attachment;
  eval {
    $attachment = $db->open_attachment($doc, 'testscript.pl')->recv;
  };
  ok((not $@), 'Get attachment contents.');
  diag $@ if $@;
  ok($attachment, 'Got attachment.');
  is($attachment, io($0)->slurp, 'Attachment unaltered upon retrieval.');
}



( run in 0.711 second using v1.01-cache-2.11-cpan-e1769b4cff6 )