EV-Etcd

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

NAME
    EV::Etcd - Async etcd v3 client using native gRPC and EV/libev

SYNOPSIS
        use v5.10;
        use EV;
        use EV::Etcd;

        my $client = EV::Etcd->new(
            endpoints => ['127.0.0.1:2379'],
        );

        $client->put('/my/key', 'value', sub {
            my ($resp, $err) = @_;
            die $err->{message} if $err;
            say "Put succeeded, revision: $resp->{header}{revision}";
        });

        $client->get('/my/key', sub {
            my ($resp, $err) = @_;
            die $err->{message} if $err;
            say "Value: $resp->{kvs}[0]{value}";
        });

        $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;

DESCRIPTION
    An asynchronous etcd v3 client on the gRPC Core C API and the EV event
    loop: a gRPC thread waits for completions and wakes the loop, and
    callbacks run in the Perl thread. It needs etcd 3.4 or later
    ("auth_status" needs 3.5).

    Every method takes a callback last; methods with options take them as a
    hash reference just before it. Invalid arguments croak. The callback
    receives "($response, $error)": the response hash and "undef", or
    "undef" and an error hash (see "ERRORS"). Responses carry a "header"
    with "cluster_id", "member_id", "revision" and "raft_term" unless noted
    otherwise. A kv hash has "key", "value", "create_revision",
    "mod_revision", "version" and "lease".

CONSTRUCTOR
  new
        my $client = EV::Etcd->new(%options);

    endpoints => [ 'host:port', ... ]
        Default "['127.0.0.1:2379']"; an empty list croaks. An endpoint may
        carry the "http://" or "https://" scheme etcd prints; "https://"
        turns on "tls".

        The client uses one endpoint at a time and moves to the next when it
        cannot be reached: a unary call fails with UNAVAILABLE, or with
        DEADLINE_EXCEEDED before a connection was made, a stream has to
        reconnect because its connection is down, or a keepalive ping goes
        unanswered. The failing call still reports its error; retrying it
        reaches the next endpoint. Several failures on one endpoint move the
        client once.

        A member that has lost its leader fails linearizable reads and
        writes after etcd's request timeout (7 seconds by default), and
        these failures move the client on too, though a shorter "timeout"
        ends the call on the client first and does not. Errors a working
        member returns during an election, such as "etcdserver: leader
        changed", do not move it.

        Streams need a leader as well: a member without one refuses new
        streams and, after a few election timeouts, ends running watches and
        keepalives with UNAVAILABLE "etcdserver: no leader". Streams retry
        such answers a second apart until a leader is back, on the next
        endpoint when there are several; each restarts the "max_retries"
        count. Once a unary call, or a stream that was running, reports
        "etcdserver: no leader", pending "lock" and "election_campaign"
        calls sent over the same connection fail with UNAVAILABLE, as they
        do when a connection that never became ready is abandoned.

        An endpoint may also be a gRPC target listing several addresses,
        such as "ipv4:10.0.0.1:2379,10.0.0.2:2379". gRPC moves between them
        within one connection, so a refused address fails no call, but never
        away from a member that has lost its leader: list members as
        separate endpoints to leave one.

        gRPC connects through a proxy named in "grpc_proxy", "https_proxy"
        or "http_proxy", even to a loopback address; list etcd's hosts in
        "no_proxy" to connect directly.

    timeout => $seconds
        RPC timeout in whole seconds, at least 1; default 30. "lock" and
        "election_campaign" wait without one, as a timeout could not tell
        whether they succeeded.

    max_retries => $count
        Reconnection attempts for a stream ("watch", "lease_keepalive",
        "election_observe") after a connection failure; default 30, 0
        disables reconnecting. Attempts are 0.5 seconds further apart each
        time, up to 5 seconds, so the default gives up about two minutes
        after the endpoints start refusing connections, plus gRPC's
        20-second connect timeout for one that accepts them but stays
        silent. Lower it to learn sooner that the endpoints are gone.

    keepalive_time => $seconds
    keepalive_timeout => $seconds
        Seconds between pings while calls or streams are open (default 10,
        fractions allowed, 0 disables them), and how long a ping may go
        unanswered (default 10). An unanswered ping closes the connection:
        its calls fail with UNAVAILABLE and the client moves to the next
        endpoint. Without pings, an endpoint that goes silent (a hung host,
        a partition) goes unnoticed until the operating system gives up on
        the connection. etcd closes connections that ping more often than
        its "--grpc-keepalive-min-time" (5 seconds by default).

    health_interval => $seconds
    on_health_change => sub { my ($healthy, $endpoint) = @_; ... }
        Every "health_interval" seconds (fractions allowed; default 0, off)
        the client checks its connection state without sending a request,
        and calls "on_health_change" when health changes. Only a failed
        connection attempt counts as unhealthy; with several endpoints it
        also moves the client on. Switching endpoints after a failed call is
        not reported.

    auth_token => $token
        A token from an earlier "authenticate", used without authenticating
        again.

    tls => $bool
        Connect with TLS; any "tls_*" option or an "https://" endpoint turns
        it on too. Without "tls_ca_file", gRPC uses its default roots, or
        the PEM bundle named by "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH".

    tls_ca_file => $path
        PEM CA certificates to verify the servers with (etcd's
        "--trusted-ca-file"), in place of the default roots. Verification
        cannot be turned off; for a self-signed server, give its certificate
        here.

    tls_cert_file => $path
    tls_key_file => $path
        Client certificate and key, given together, for servers started with
        "--client-cert-auth".

    tls_server_name => $name
        Name to verify the server certificate against and send as SNI, in
        place of the endpoint's host.

        my $client = EV::Etcd->new(
            endpoints     => ['https://10.0.0.1:2379', 'https://10.0.0.2:2379'],
            tls_ca_file   => '/etc/etcd/ca.crt',
            tls_cert_file => '/etc/etcd/client.crt',
            tls_key_file  => '/etc/etcd/client.key',
        );

ERRORS
        {
            code      => 14,                    # gRPC status code
            status    => 'UNAVAILABLE',
            message   => 'Connection refused',
            source    => 'range',               # the call that failed
            retryable => 1,
        }

    "source" is the method name, except "range" for "get", "lease_ttl" for
    "lease_time_to_live", "keepalive" for "lease_keepalive", "campaign",
    "proclaim", "leader", "resign" and "observe" for the "election_*" calls,
    and "internal" for a unary response the client could not read.

    "retryable" is set for UNAVAILABLE, ABORTED, DEADLINE_EXCEEDED and
    RESOURCE_EXHAUSTED "etcdserver: too many requests", but never for a
    failed "lock" or "election_campaign". Other RESOURCE_EXHAUSTED errors
    last until someone intervenes, such as "etcdserver: mvcc: database space
    exceeded" (see "alarm"). Retryable means transient, not without effect:
    a write can be applied after its deadline has passed, so retrying
    "lease_grant", "lease_revoke" or "delete" can apply it twice or report
    what the first attempt did.

    Unary calls are not retried. Streams reconnect on their own (see
    "max_retries"), to the next endpoint once the current one has failed,
    and the count restarts once a stream is working again. A stream reports
    an error when reconnecting is disabled or exhausted, at once for a
    status a new connection cannot fix (UNAUTHENTICATED, PERMISSION_DENIED,
    INVALID_ARGUMENT, NOT_FOUND, ALREADY_EXISTS, FAILED_PRECONDITION,
    OUT_OF_RANGE, UNIMPLEMENTED), and for an error the server sends on it,
    such as a cancelled or compacted watch or an expired lease, which ends
    it.

    The server can still clean up after a failed "lock" or
    "election_campaign" has reported, deleting the key it made on the lease.
    Retry with a fresh lease, and revoke the old one (which deletes all its
    keys) or let it expire, as a stale candidate on it can block the new
    attempt.

CALLBACKS AND HANDLES
    A callback that dies stops neither the loop nor the client: the
    exception goes to $EV::DIED, a warning by default.

    Callbacks live in C structures Perl cannot see, so a closure that
    captures its client or stream handle keeps it alive until the stream is
    cancelled or the client destroyed; capture a weakened copy instead.
    Dropping a handle does not cancel its stream. Destroying a client
    cancels its calls and streams without calling their callbacks. A client
    keeps "EV::run" running while it exists: destroy it or call "EV::break"
    to leave the loop. Only EV's default loop runs the callbacks, never a
    loop from "EV::Loop->new".

        use Scalar::Util 'weaken';
        weaken(my $weak = $client);
        my $watch = $client->watch('/jobs', sub {
            my ($resp, $err) = @_;
            $weak->put('/seen', 1, sub {}) if $weak && !$err;
        });

  cancel
        $handle->cancel($callback);

    "watch", "lease_keepalive" and "election_observe" return a handle
    ("EV::Etcd::Watch", "EV::Etcd::Keepalive", "EV::Etcd::Observe") whose
    "cancel" ends the stream. The callback runs before "cancel" returns,
    with an empty hash as the response, and the stream delivers nothing
    after it. Cancelling again is safe and does the same.

ENCODING
    etcd stores keys and values as bytes and the client does no encoding: a
    string with the UTF-8 flag is stored as its UTF-8 bytes, and responses
    hold byte strings. Use "encode_utf8" and "decode_utf8" from Encode at
    the boundary for character data.

    A key or value over 1 MiB croaks before anything is sent. etcd refuses a
    request over its "--max-request-bytes" (1.5 MiB by default) with
    INVALID_ARGUMENT "etcdserver: request is too large", and gRPC one 512
    KiB larger still with RESOURCE_EXHAUSTED.

KEY-VALUE
  put
        $client->put($key, $value, [\%opts,] $callback);

    lease => $lease_id
        Attach the key to a lease.



( run in 0.872 second using v1.01-cache-2.11-cpan-16aabcbfbcb )