APNS-Agent

 view release on metacpan or  search on metacpan

lib/APNS/Agent.pm  view on Meta::CPAN

                warnf "identifier:%s\tstate:%s\ttoken:%s", $d{identifier}, $d{state}, $d{token} || '';
            }
        },
        disconnect_interval => sub { 60 },
        send_interval       => sub { 0.01 },
        _sent_cache         => sub { Cache::LRU->new(size => 10000) },
        _queue              => sub { [] },
        __apns              => '_build_apns',
        _sent               => sub { 0 },
    },
    rw => [qw/_last_sent_at _disconnect_timer/],
);

sub to_app {
    my $self = shift;

    my $router = Router::Boom::Method->new;
    $router->add(POST => '/'        => '_do_main');
    $router->add(GET  => '/monitor' => '_do_monitor');

    sub {

lib/APNS/Agent.pm  view on Meta::CPAN

sub _build_apns {
    my $self = shift;

    AnyEvent::APNS->new(
        certificate => $self->certificate,
        private_key => $self->private_key,
        sandbox     => $self->sandbox,
        on_error    => sub {
            my ($handle, $fatal, $message) = @_;

            my $t; $t = AnyEvent->timer(
                after    => 0,
                interval => 10,
                cb       => sub {
                    undef $t;
                    infof "event:reconnect";
                    $self->_connect_to_apns;
                },
            );
            warnf "event:error\tfatal:$fatal\tmessage:$message";
        },
        on_connect  => sub {
            infof "event:on_connect";
            $self->_disconnect_timer($self->_build_disconnect_timer);

            if (@{$self->_queue}) {
                $self->_sending;
            }
        },
        on_error_response => sub {
            my ($identifier, $state) = @_;
            my $data = $self->_sent_cache->get($identifier) || {};
            $self->on_error_response->($self, {
                identifier => $identifier,

lib/APNS/Agent.pm  view on Meta::CPAN


sub _apns {
    my $self = shift;

    my $apns = $self->__apns;
    $apns->connect unless $apns->connected;
    $apns;
}
sub _connect_to_apns { goto \&_apns }

sub _build_disconnect_timer {
    my $self = shift;

    if (my $interval = $self->disconnect_interval) {
        AnyEvent->timer(
            after    => $interval,
            interval => $interval,
            cb       => sub {
                if ($self->{__apns} && (time - ($self->_last_sent_at || 0) > $interval)) {
                    delete $self->{__apns};
                    delete $self->{_disconnect_timer};
                    infof "event:close apns";
                }
            },
        );
    }
    else { undef }
}

sub _sending {
    my $self = shift;

    $self->{_send_timer} ||= AnyEvent->timer(
        after    => $self->send_interval,
        interval => $self->send_interval,
        cb       => sub {
            my $msg = shift @{ $self->_queue };
            if ($msg) {
                $self->_send(@$msg);
            }
            else {
                delete $self->{_send_timer};
            }
        },
    );
}

sub _send {
    my ($self, $token, $payload) = @_;

    local $@;
    my $identifier;
    eval {
        $identifier = $self->_apns->send(pack("H*", $token) => {
            aps => $payload,
        });
    };

    if (my $err = $@) {
        if ($err =~ m!Can't call method "push_write" on an undefined value!) {
            # AnyEvent::APNS->handle is missing
            delete $self->{_send_timer};
            unshift @{ $self->_queue }, [$token, $payload];
            $self->_connect_to_apns;
        }
        else {
            die $err;
        }
    }
    else {
        $self->_sent_cache->set($identifier => {
            token   => $token,



( run in 0.458 second using v1.01-cache-2.11-cpan-49f99fa48dc )