NAME

Net::Object::Peer - Peer-to-Peer Publish/Subscribe Network of Objects

VERSION

version 0.02

SYNOPSIS

use 5.10.0;

package Node;
use Moo;
with 'Net::Object::Peer';

has name => is => ( 'ro', required => 1 );

sub _notify_subscribed {
    my ( $self, $peer, $name ) = @_;
    say $self->name, ":\t@{[ $peer->name ]} subscribed to event $name";
}

sub _cb_hey {
    my ( $self, $event ) = @_;
    say $self->name,
      ":\t@{[ $event->emitter->name ]} sent @{[$event->name]}";
}

sub _cb_unsubscribe {
    my ( $self, $event ) = @_;
    say $self->name, ":\t@{[ $event->emitter->name ]} unsubscribed";
}

package main;


my $n1 = Node->new( name => 'N1' );
my $n2 = Node->new( name => 'N2' );
my $n3 = Node->new( name => 'N3' );

# Net::Object::Peer provides an "unsubscribe" event; $n1 will be
# notified when $n2 unsubscribes from it
$n1->subscribe( $n2, 'unsubscribe' );

# $n2 and $n3 will be notified when $n1 sends a "hey" event, and $n1
# will be notified that they have subscribed 

$n2->subscribe( $n1, 'hey' );
$n3->subscribe( $n1, 'hey' );

# both $n2 and $n3 will get notified
$n1->emit( 'hey' );

# only $n2 gets notified
$n1->send( $n2, 'hey' );

# destroy $n2; $n2 will unsubscribe from all of its events and $n1
# will be notified that $n2 has unsubscribed from it.
undef $n2;

Resulting in:

N2:	N1 subscribed to event unsubscribe
N1:	N2 subscribed to event hey
N1:	N3 subscribed to event hey
N2:	N1 sent hey
N3:	N1 sent hey
N2:	N1 sent hey
N1:	N2 unsubscribed

DESCRIPTION

Net::Object::Peer is a Moo Role which implements a publish/subscribe peer-to-peer messaging system, based upon Beam::Emitter. Objects in the network may broadcast events to all subscribers or may send events to a particular subscriber.

Subscriptions and unsubscriptions are tracked and messages will be sent to affected objects upon request.

While Net::Object::Peer is designed around the concept of nodes being objects with methods as event handlers, it retains Beam::Emitter's ability to register code references as well.

Net::Object::Peer::Cookbook provides some recipes.

Usage

As Net::Object::Peer is purely peer based with no common message bus, a network is built up by creating a set of network nodes and linking them via subscriptions.

my $n1 = Node->new( name => 'N1' );
my $n2 = Node->new( name => 'N2' );

$n1->subscribe( $n2, 'changed' );

Here $n1 subscribes to $n2's changed event. By default, $n1's _cb_changed method is invoked when $n2 emits a changed event.

Events

When a subscriber recieves an event, its registered handler for that event type is invoked. If the object creating the event used the "emit" or "send" methods,

$emitter->emit( $event_name );

the event handler will be invoked as

$subscriber->method( $event );

where $event is an object derived from the Net::Object::Peer::Event class. (This assumes that the handler is a method; it may be a simple callback).

If the event was created with the "emit_args" or "send_args" methods,

$emitter->emit_args( $event_name, @arguments );

the event handler will invoked as

$subscriber->method( @arguments );

Subscription and Unsubscription Events

When a subscriber registers one or more event handlers with an emitter via the subscriber's "subscribe" method, the emitter's _notify_subscribed method will be invoked (if it exists) as

$emitter->_notify_subscribed( $subscriber, @event_names );

After a subscriber de-registers a handler, either explicitly via "unsubscribe" or when the object is destroyed, it will "emit" an unsubscribe event with a Net::Object::Peer::UnsubscribeEvent object as a payload.

While emitters are not automatically subscribed to "unsubscribe" events, this is easily accomplished by adding code to the emitters' _notify_subscribed method.

METHODS

build_sub

$coderef = $self->build_sub( $emitter, @tuple );

build_sub is the method responsible for creating and compiling the code for an event handler. It is invoked from the "subscribe()" method, with the following parameters

$emitter

The emitter object.

@tuple

the tuple passed to "subscribe" for this event.

The default implementation will return a Sub::Quote::quote_sub generated code reference for method calls and code specified as a string. See "Loop Detecton" in Net::Object::Peer::Cookbook for an example of using this attribute to inline additional code in the event handler.

subscribe

$self->subscribe( $peer, @event_tuple [, @event_tuple, ...  ] );

Subscribe to one or more events sent by $peer, which must consume the Net::Object::Peer role.

The event name and the action to be performed when the event is emitted are specified by a tuple with the following forms:

$event_name

the event handler will invoke the _cb_${event_name} method on $self.

$event_name => { method => $method_name }

The event handler will invoke the $method_name method on $self.

$event_name => CODEREF

The passed code reference is called.

$event_name => { code => $code, capture => \%capture }

$code is a string containing code to be run by the event handler. %capture is a hash containing variable captures. See the documentation for "\%captures" in "quote_sub" in Sub::Quote for more information.

If $peer provides a _notify_subscribed method, that will be invoked as

$peer->_notify_subscribed( $self, $event_name, ... );

for each subscription.

unsubscribe

# Unsubscribe from all events from all peers.
$self->unsubscribe;

# Unsubscribe from all events emitted by a peer
$self->unsubscribe( $peer );

# Unsubscribe from one or more events emitted by a peer
$self->unsubscribe( $peer, $event_name [, $event_name [, ... ]);

# Unsubscribe from one or more events emitted by all peers
$self->unsubscribe( $event_name [, $event_name [, ... ] ] )

Unsubscribe from events/peers. After unsubscription, an unsubscribe event with a Net::Object::Peer::UnsubscribeEvent as a payload will be sent to affected peers who have subscribed to the unsubscribed event(s).

subscriptions

my @subscriptions = $self->subscriptions;

Returns the events to which $self is subscribed as a list of Net::Object::Peer::Subscription objects.

emit

$self->emit( $event_name, %args );

Broadcast the named event to all subscribed peers. %args contains arguments to be passed the the payload class constructor. The default payload class is a Net::Object::Peer::Event object; use the class key to specify an alternate class, which must be erived from Net::Object::Peer::Event.

send

$self->send( $peer, $event_name, %args );

This is similar to the "emit" method, but only sends the event to the specified peer.

emit_args

$self->emit_args( $event_name, @args );

Broadcast the named event to all subscribed peers. @args will be passed directly to each subscriber's callback.

send_args

$self->send_args( $peer, $event_name, @args );

This is similar to the "emit_args" method, but only sends the event to the specified peer.

AUTHOR

Diab Jerius <djerius@cpan.org>

COPYRIGHT AND LICENSE

This software is Copyright (c) 2016 by Smithsonian Astrophysical Observatory.

This is free software, licensed under:

The GNU General Public License, Version 3, June 2007