AnyEvent-KVStore-Etcd
view release on metacpan or search on metacpan
lib/AnyEvent/KVStore/Etcd.pm view on Meta::CPAN
but there are some important limitations discussed here.
This module can also be used directly for simplified access to an Etcd database.
=head2 AnyEvent Loops, Callbacks, and KVStore Operations
Net::Etcd uses L<AnyEvent::HTTP> for its transport layer. It further blocks in
an L<AnyEvent> loop to wait for the response. For obvious reasons, this does
not work. So, the main key/value operations cannot be done from inside an
event loop. This leads to a number of possible solutions including forking and
running the request in another process.
One option, though it does incur significant startup cost, is to use L<Coro>
and move the callback from a C<sub {}> call to an C<unblock_sub {}> call. This
is probably the simplest approach and it works. In general you get sequential
ordering but this is not a hard guarantee. Another approach might be to move
processing into worker threads.
=head1 ATTRIBUTES/ACCESSORS
If accessing the module directly, the following accessors are available. These
are not generally needed and are mostly used internally for managing the
connection to the etcd server.
These are also keys for the config hash.
All attributes are optional.
=head2 host Str
This is the hostname for the etcd connection. It defaults to localhost.
=cut
has host => (is => 'ro', isa => Str, default => sub { 'localhost' });
=head2 port Int
Port for connection. It defaults to 2379.
=cut
has port => (is => 'ro', isa => Int, default => sub { 2379 } );
=head2 ssl Bool default false
whether to use SSL or not. The default is no.
=cut
has ssl => (is => 'ro', isa => Bool, default => 0);
=head2 user Str
Username for authentication. Does not authenticate if not set.
=cut
has user => (is => 'ro', isa => Str);
=head2 password Str
Password for authentication.
=cut
has password => (is => 'ro', isa => Str);
=head2 cnx Net::Etcd
This is the active connection to the etcd database.
=cut
# $self->_slice returns a hashref with the properties requested.
# This relies on the fact that Moo(se) objects are blessed hashrefs.
sub _slice {
my $self = shift;
my @vars = @_;
return { %{$self}{@vars} };
}
sub _etcd_connect {
my $self = shift;
my $cnx = Net::Etcd->new($self->_slice('host', 'port', 'ssl'));
die 'Could not create new etcd connection' unless $cnx;
$cnx->auth($self->_slice('user', 'password'))->authenticate if $self->user;
return $cnx;
}
has cnx => (is => 'ro', builder => '_etcd_connect', lazy => 1);
=head1 METHODS
=head2 read
Reads a value from a key and returns a JSON document payload.
=cut
sub read($$) {
my ($self, $key) = @_;
my $value = $self->cnx->range({key => $key })->{response}->{content};
$value = decode_json($value)->{kvs}->[0]->{value};
return decode_base64($value);
}
=head2 exists
Checks to see if a key exists. Here this is no less costly than read.
=cut
sub exists($$) {
my ($self, $key) = @_;
my $value = $self->cnx->range({key => $key })->{response}->{content};
$value = decode_json($value)->{kvs}->[0]->{value};
return defined $value;;
}
=head2 list($pfx)
Returns a list of keys
=cut
# adds one to the binary representation of the string for prefix searches
sub _add_one($){
my ($str) = @_;
if ($str =~ /^\xff*$/){ # for empty string too
return "\x00";
}
my $inc = $str;
$inc =~ s/([^\xff])\xff*\z/ $1 =~ tr||\x01-\xff|cr /e;
return $inc;
}
sub list($$) {
my ($self, $pfx) = @_;
my $value = $self->cnx->range({key => $pfx, range_end => _add_one($pfx)})->{response}->{content};
return map { decode_base64($_->{key} ) } @{decode_json($value)->{kvs}};
}
( run in 0.950 second using v1.01-cache-2.11-cpan-bbe5e583499 )