AnyEvent-CouchDB
view release on metacpan or search on metacpan
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)
- 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)
- $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)
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
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 )