NAME
Net::Object::Peer - Peer-to-Peer Publish/Subscribe Network of Objects
VERSION
version 0.04
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 );
If the subscription already exists, it will be unsubscribed and then resubscribed.
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.
Detach Events
When an object is destroyed, it emits a detach
event after unsubscribing from other peers' events.
ATTRIBUTES
addr
A Net::Object::Peer::RefAddr object providing a unique identity for this emitter.
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. If $peer
additionally consumes the Net::Object::Peer::Ephemeral role, a strong reference to $peer
is stored. (See "Translation/Proxy Nodes" in Net::Object::Peer::Cookbook.)
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 the peer and event specified by the passed
# Net::Object::Peer::Event object
$self->unsubscribe( $event_object );
# 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).
$peer
may be either a Net::Object::Peer or a Net::Object::Peer::RefAddr object.
Note that Net::Object::Peer::Event objects which are passed to event handlers may have a masqueraded emitter
attribute. Attempting to unsubscribe from that emitter
is unwise. Instead, pass either the event object or the addr
field in that object, which is guaranteed to identify the actual emitter subscribed to.
detach
$self->detach;
Detach the object from the network. It will
Unsubscribe from all events from all peers.
Emit an
unsubscribe
event with a Net::Object::Peer::UnsubscribeEvent as a payload.Emit a
detach
event.
subscriptions
# return all subscriptions
my @subscriptions = $self->subscriptions;
# return matching subscriptions
my @subscriptions = $self->subscriptions( $coderef | %spec );
Returns the events to which $self
is subscribed as a list of hashrefs (see Net::Object::Peer::Subscription::as_hashref). If arguments are specified, only those which match are returned; see "find" in Net::Object::Peer::Subscrition;
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 derived 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