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