EV-Etcd
view release on metacpan or search on metacpan
eg/watch_config_tree.pl view on Meta::CPAN
#!/usr/bin/env perl
#
# Example: Mirror an etcd prefix into a local nested hash using Data::Path::XS
# (optional CPAN module â install separately to run this example).
#
# etcd keys like /myapp/db/host -> "localhost" become:
# $config = { db => { host => "localhost" } }
#
use strict;
use warnings;
use lib 'blib/lib', 'blib/arch';
use EV;
use EV::Etcd;
use Data::Path::XS qw(path_get path_set path_delete);
use Data::Dumper;
my $prefix = "/myapp/";
my %config;
my $client = EV::Etcd->new(endpoints => ['127.0.0.1:2379']);
# Seed some data
print "=== Seeding config ===\n";
$client->txn(
compare => [],
success => [
{ put => { key => "${prefix}db/host", value => "localhost" } },
{ put => { key => "${prefix}db/port", value => "5432" } },
{ put => { key => "${prefix}cache/host", value => "redis.local" } },
{ put => { key => "${prefix}cache/ttl", value => "3600" } },
],
failure => [],
sub {
my ($resp, $err) = @_;
die "Seed failed: $err->{message}" if $err;
EV::break;
}
);
my $t0 = EV::timer(5, 0, sub { die "timeout" });
EV::run;
# Load initial snapshot into tree
$client->get($prefix, { prefix => 1 }, sub {
my ($resp, $err) = @_;
die "Load failed: $err->{message}" if $err;
for my $kv (@{$resp->{kvs} || []}) {
my $path = substr($kv->{key}, length($prefix) - 1); # keep leading /
path_set(\%config, $path, $kv->{value});
}
print "Initial config tree:\n", Dumper(\%config);
# Watch from next revision â no gap between load and watch
my $rev = $resp->{header}{revision} + 1;
$client->watch($prefix, { prefix => 1, start_revision => $rev }, sub {
my ($resp, $err) = @_;
if ($err) {
print "Watch error: $err->{message}\n";
return;
}
for my $ev (@{$resp->{events} || []}) {
my $path = substr($ev->{kv}{key}, length($prefix) - 1);
if (($ev->{type} // 'PUT') eq 'DELETE') {
path_delete(\%config, $path);
print "DELETE $path\n";
} else {
path_set(\%config, $path, $ev->{kv}{value});
print "PUT $path = $ev->{kv}{value}\n";
}
}
print "Config tree:\n", Dumper(\%config);
});
EV::break;
});
my $t1 = EV::timer(5, 0, sub { die "timeout" });
EV::run;
( run in 0.605 second using v1.01-cache-2.11-cpan-524268b4103 )