EV-Etcd
view release on metacpan or search on metacpan
lib/EV/Etcd.pm view on Meta::CPAN
use EV;
use EV::Etcd;
my $client = EV::Etcd->new(
endpoints => ['127.0.0.1:2379'],
);
# Async put
$client->put('/my/key', 'value', sub {
my ($resp, $err) = @_;
die $err->{message} if $err;
say "Put succeeded, revision: $resp->{header}{revision}";
});
# Async get
$client->get('/my/key', sub {
my ($resp, $err) = @_;
die $err->{message} if $err;
say "Value: $resp->{kvs}[0]{value}";
});
# Watch
$client->watch('/my/key', sub {
my ($resp, $err) = @_;
return warn "Watch error: $err->{message}\n" if $err;
for my $event (@{$resp->{events}}) {
say "Event: $event->{type} on $event->{kv}{key}";
}
});
EV::run;
=head1 DESCRIPTION
EV::Etcd provides a high-performance async client for etcd v3 using native
gRPC Core C API integrated with the EV event loop.
=head1 METHODS
=head2 new
my $client = EV::Etcd->new(%options);
Options:
=over 4
=item endpoints
ArrayRef of etcd endpoints (host:port). Optional; defaults to
C<['127.0.0.1:2379']>. When more than one is provided, the client uses the
first endpoint and rotates to subsequent endpoints on connection failure.
=item timeout
RPC timeout in seconds. Default is 30 seconds. Minimum value is 1 second.
=item max_retries
Maximum number of reconnection attempts for streaming operations (watch,
lease_keepalive, election_observe) after a connection failure. Default is 3.
Set to 0 to disable automatic reconnection.
=item health_interval
Interval in seconds for health monitoring. Default is 0 (disabled).
When enabled, the client periodically checks the gRPC channel connectivity
state and calls the on_health_change callback when the connection state changes.
=item on_health_change
Callback called when the connection health status changes. Receives two
arguments: a boolean indicating health status (1=healthy, 0=unhealthy) and
the current endpoint string.
my $client = EV::Etcd->new(
endpoints => ['127.0.0.1:2379'],
health_interval => 5,
on_health_change => sub {
my ($is_healthy, $endpoint) = @_;
warn $is_healthy ? "Connected to $endpoint" : "Disconnected from $endpoint";
},
);
=item auth_token
Pre-set authentication token. Use this to create an authenticated client
without calling authenticate() first. Useful when you already have a valid
token from a previous session.
my $client = EV::Etcd->new(
endpoints => ['127.0.0.1:2379'],
auth_token => $saved_token,
);
=back
=head1 ENCODING
Keys and values are stored by etcd as raw bytes; this module does not perform
any character encoding. If you pass a Perl string with the UTF-8 flag set
(e.g. a literal containing non-ASCII characters under C<use utf8>), the UTF-8
byte representation is what gets stored. Values returned by C<get> are byte
strings without the UTF-8 flag â string-equality with the original literal
will fail unless you decode explicitly.
For character data, encode/decode at the boundary using L<Encode>:
use Encode qw(encode_utf8 decode_utf8);
$client->put($key, encode_utf8($value), sub { ... });
$client->get($key, sub {
my ($resp) = @_;
my $value = decode_utf8($resp->{kvs}[0]{value});
});
=head1 ERROR HANDLING
Errors are returned as hash references with the following structure:
{
code => 14, # gRPC status code (integer)
status => "UNAVAILABLE", # gRPC status name (string)
message => "Connection refused", # Error message
source => "get", # Which operation failed
retryable => 1, # Whether the error is retryable
}
The C<retryable> field indicates whether the error is transient (status codes:
UNAVAILABLE, RESOURCE_EXHAUSTED, ABORTED, DEADLINE_EXCEEDED).
Streaming operations (watch, keepalive, observe) automatically reconnect
on transient failures according to the C<max_retries> configuration.
Unary RPCs (get, put, delete, etc.) do not retry automatically; use the
C<retryable> field to implement application-level retry logic.
=head1 KEY-VALUE OPERATIONS
=head2 put
$client->put($key, $value, $callback);
$client->put($key, $value, \%opts, $callback);
Put a key-value pair into etcd.
Options:
=over 4
=item lease
Lease ID to associate with the key.
=item prev_kv
If true, returns the previous key-value pair in the response.
=item ignore_value
If true, updates the lease without changing the value.
=item ignore_lease
If true, updates the value without changing the lease.
=back
The callback receives C<($response, $error)>. Response keys: C<header>, plus
C<prev_kv> (a kv hashref) when the C<prev_kv> option is set.
=head2 get
$client->get($key, $callback);
$client->get($key, \%opts, $callback);
Get key(s) from etcd.
Options:
=over 4
=item prefix
If true, returns all keys with the given prefix.
=item range_end
End of the key range to query.
=item limit
Maximum number of keys to return.
lib/EV/Etcd.pm view on Meta::CPAN
# Process events...
});
=back
=head2 EV::Etcd::Watch Methods
=head3 cancel
$watch->cancel($callback);
Cancel the watch. The callback receives C<($response, $error)> when
cancellation is complete. The response is an empty hash reference on success.
Calling C<cancel> on an already-cancelled handle is safe: the callback fires
immediately with success. The handle remains valid as a Perl reference until
you drop it.
$watch->cancel(sub {
my ($resp, $err) = @_;
if ($err) {
warn "Cancel failed: $err->{message}";
} else {
print "Watch cancelled\n";
}
});
=head1 LEASE SERVICE
=head2 lease_grant
$client->lease_grant($ttl, $callback);
Grant a lease with the specified TTL (time-to-live) in seconds.
The callback receives C<($response, $error)>. Response keys:
=over 4
=item id
The lease ID.
=item ttl
The actual TTL granted by the server.
=item header
Standard response header.
=back
=head2 lease_revoke
$client->lease_revoke($lease_id, $callback);
Revoke a lease. All keys attached to the lease will be deleted. The response
contains C<header> only.
=head2 lease_keepalive
my $keepalive = $client->lease_keepalive($lease_id, $callback);
my $keepalive = $client->lease_keepalive($lease_id, \%opts, $callback);
Keep a lease alive. Creates a bidirectional streaming connection that keeps
the lease refreshed. Returns an C<EV::Etcd::Keepalive> object that can be
used to cancel the keepalive stream:
$keepalive->cancel(sub { my ($resp, $err) = @_; });
Options:
=over 4
=item auto_reconnect
If true, the keepalive stream will automatically reconnect after a connection
failure, with exponential backoff up to C<max_retries> (set on the client).
Default is 1 (enabled). Pass C<0> to disable.
=back
The keepalive callback receives C<($response, $error)> for each tick. On
success the response includes C<id>, C<ttl>, and C<header>. When the lease
has expired the server sends C<ttl=0>; the client maps that to an error
callback with C<< source => "keepalive" >> and status C<NOT_FOUND>.
=head2 EV::Etcd::Keepalive Methods
=head3 cancel
$keepalive->cancel($callback);
Cancel the keepalive stream. The callback receives C<($response, $error)>
when cancellation is complete. The response is an empty hash reference on
success.
Calling C<cancel> on an already-cancelled handle is safe: the callback fires
immediately with success. The handle remains valid as a Perl reference until
you drop it.
=head2 lease_time_to_live
$client->lease_time_to_live($lease_id, $callback);
$client->lease_time_to_live($lease_id, \%opts, $callback);
Get the remaining TTL of a lease.
Options:
=over 4
=item keys
If true, also return the list of keys attached to this lease.
=back
The callback receives C<($response, $error)>. Response keys:
=over 4
=item id
The lease ID.
=item ttl
Remaining TTL in seconds. Returns -1 if the lease has expired.
=item granted_ttl
The original TTL granted when the lease was created.
=item keys
Array of keys attached to this lease (only when the C<keys> option is true).
=item header
Standard response header.
=back
=head2 lease_leases
$client->lease_leases($callback);
List all active leases. The callback receives C<($response, $error)>.
Response keys: C<header>, and C<leases> â an array of hashrefs each with an
C<id> key.
=head1 LOCK SERVICE
EV::Etcd provides distributed locking through the etcd Lock service.
Locks are tied to leases - when the lease expires or is revoked, the lock
is automatically released.
=head2 lock
$client->lock($name, $lease_id, $callback);
Acquire a distributed lock.
Arguments:
=over 4
=item name
The name (identifier) of the lock to acquire. This is a byte string that
identifies the resource being locked. Multiple clients attempting to lock
the same name will block until the lock is available.
=item lease_id
The ID of a lease to attach to the lock. The lock will be held for the
duration of the lease. If the lease expires or is revoked, the lock is
automatically released. You must first create a lease with C<lease_grant>
and optionally keep it alive with C<lease_keepalive>.
=item callback
Called with C<($response, $error)> when the lock is acquired (or fails).
=back
The response contains:
=over 4
=item key
The key that holds the lock. This key is used to unlock the lock and
should be stored by the caller. The key is unique to this lock holder
and contains the lock name as a prefix.
=item header
Standard response header with cluster_id, member_id, revision, and raft_term.
=back
Example:
# First, create a lease for the lock
$client->lease_grant(30, sub {
my ($lease_resp, $err) = @_;
die $err->{message} if $err;
my $lease_id = $lease_resp->{id};
# Now acquire the lock
$client->lock("my-resource", $lease_id, sub {
my ($lock_resp, $err) = @_;
die $err->{message} if $err;
my $lock_key = $lock_resp->{key};
print "Lock acquired with key: $lock_key\n";
# ... do protected work ...
# Release the lock when done
$client->unlock($lock_key, sub {
my ($unlock_resp, $err) = @_;
warn "Unlock failed: $err->{message}" if $err;
});
});
});
=head2 unlock
$client->unlock($key, $callback);
Release a distributed lock.
Arguments:
=over 4
lib/EV/Etcd.pm view on Meta::CPAN
$client->move_leader($target_id, $callback);
Transfer leadership to another member. Only the current leader can
transfer leadership.
Arguments:
=over 4
=item target_id
The member ID of the new leader. Must be a voting member (not a learner).
=item callback
Called with C<($response, $error)> when the operation completes.
=back
The response contains:
=over 4
=item header
Standard response header.
=back
Example:
# Get current cluster status to find member IDs
$client->member_list(sub {
my ($resp, $err) = @_;
my $target = $resp->{members}[1]{id}; # Pick a different member
$client->move_leader($target, sub {
my ($resp, $err) = @_;
if ($err) {
warn "Failed to move leader: $err->{message}";
} else {
say "Leadership transferred";
}
});
});
=head1 ELECTION SERVICE
EV::Etcd provides leader election support through the etcd Election service.
Elections use leases to ensure that leadership is automatically released
when a leader fails.
=head2 election_campaign
$client->election_campaign($name, $lease_id, $value, $callback);
Campaign for leadership of an election.
This call blocks until the caller is elected as leader. Once elected, the
caller should periodically keep the lease alive to maintain leadership.
Arguments:
=over 4
=item name
The name of the election to campaign in.
=item lease_id
The lease ID to use for the campaign. The leadership is held for the
duration of this lease.
=item value
The value to set when elected. Other clients can read this value to
identify the current leader.
=item callback
Called with C<($response, $error)> when elected (or on failure).
=back
The response contains:
=over 4
=item leader
A hash containing the leader key information:
=over 4
=item name
The election name.
=item key
The key in etcd that holds the leadership (use for proclaim/resign).
=item rev
The creation revision of the leader key.
=item lease
The lease ID attached to the leadership.
=back
=item header
Standard response header.
=back
Example:
( run in 1.402 second using v1.01-cache-2.11-cpan-d8267643d1d )