Mercury
view release on metacpan or search on metacpan
lib/Mercury/Controller/PubSub/Cascade.pm view on Meta::CPAN
#pod This endpoint requires a C<topic> in the stash.
#pod
#pod =cut
sub subscribe {
my ( $c ) = @_;
my $pattern = $c->_pattern( $c->stash( 'topic' ) );
$pattern->add_subscriber( $c->tx );
$c->rendered( 101 );
}
#pod =method post
#pod
#pod Post a new message to the given topic without subscribing or
#pod establishing a WebSocket connection. This allows new messages to be
#pod pushed by any HTTP client.
#pod
#pod =cut
sub post {
my ( $c ) = @_;
my $topic = $c->stash( 'topic' );
my $pattern = $c->_pattern( $topic );
$pattern->send_message( $c->req->body );
$c->_send_message( $topic, $c->req->body );
$c->render(
status => 200,
text => '',
);
}
#=method _pattern
#
# my $pattern = $c->_pattern( $topic );
#
# Get or create the L<Mercury::Pattern::PubSub> object for the given
# topic.
#
#=cut
sub _pattern {
my ( $c, $topic ) = @_;
my $pattern = $c->mercury->pattern( 'PubSub::Cascade' => $topic );
if ( !$pattern ) {
$pattern = Mercury::Pattern::PubSub->new;
$c->mercury->pattern( 'PubSub::Cascade' => $topic => $pattern );
}
return $pattern;
}
#=method _send_message
#
# $c->_send_message( $topic, $msg );
#
# Send the given message out on all the appropriate topics. This handles
# the "Cascade" part.
#=cut
sub _send_message {
my ( $c, $topic, $msg ) = @_;
my @parts = split m{/}, $topic;
my @patterns =
# Only pattern objects that have been created
grep { defined }
# Change topics into pattern objects
map { $c->mercury->pattern( 'PubSub::Cascade' => $_ ) }
# Build parent topics
map { join '/', @parts[0..$_] }
0..$#parts-1;
$_->send_message( $msg ) for @patterns;
}
1;
__END__
=pod
=head1 NAME
Mercury::Controller::PubSub::Cascade - Pub/sub controller with a topic heirarchy and cascading
=head1 VERSION
version 0.016
=head1 SYNOPSIS
# myapp.pl
use Mojolicious::Lite;
plugin 'Mercury';
websocket( '/pub/*topic' )
->to( controller => 'PubSub::Cascade', action => 'pub' );
websocket( '/sub/*topic' )
->to( controller => 'PubSub::Cascade', action => 'sub' );
=head1 DESCRIPTION
This controller enables a L<pubE<sol>sub pattern|Mercury::Pattern::PubSub> on
a pair of endpoints (L<publish|/publish> and L<subscribe|/subscribe>.
In this variant, topics are organized into a heirarchy. Subscribers can
subscribe to higher branch of the tree to recieve messages from all the
publishers on lower branches of the tree. So, a subscriber to C</foo>
will receive messages sent to C</foo>, C</foo/bar>, and C</foo/bar/baz>.
For more information on the pub/sub pattern, see L<Mercury::Pattern::PubSub>.
=head1 METHODS
=head2 publish
$app->routes->websocket( '/pub/*topic' )
->to( controller => 'PubSub::Cascade', action => 'publish' );
Controller action to connect a websocket as a publisher. A publish
client sends messages through the socket. The message will be sent to
all of the connected subscribers for the topic and all parent topics.
This endpoint requires a C<topic> in the stash.
( run in 1.562 second using v1.01-cache-2.11-cpan-71847e10f99 )