NAME
Jifty::Plugin::PubSub - Event-based publish/subscribe framework
SYNOPSIS
In etc/config.yml:
Plugins:
- PubSub: {}
In a region:
Jifty->subs->update_on( topic => "some_event" );
In a model:
Jifty->bus->publish( "some_event" );
DESCRIPTION
Generating events
The most basic aspect of event-based communication is the publishing of messages. This is done via:
Jifty->bus->publish( "some_event" => {
some_key => "data",
});
This notifies all subscribers of the some_event
class with the arbitrary payload specified. See AnyMQ for more details of the backend data bus. The type
key of the data provided is reserved for internal routing.
Consuming events outside the webserver
<Jifty-
bus>> is an AnyMQ bus; as such, the standard ways of consuming apply here:
my $listen = Jifty->bus->new_listener;
$listen->subscribe( Jifty->bus->topic("some_event") );
$listen->poll( sub {
my ($data) = @_;
warn "Got some event with " . $data->{some_key};
}
# Loop forever
AE::cv->recv;
Pushing updated regions to the client
A region can request that it should be updated in the client when an event is received. At the most basic, this is done via:
Jifty->subs->update_on( topic => "some_event" );
Events may trigger arbitrary other region updates, using:
Jifty->subs->add(
topic => "some_event",
region => "...",
path => "...",
# Any other arguments from Jifty::Form::Element
);
When a region is rendered because it was triggered by an event, it will be passed the triggering event in an event
variable.
Running javascript in the client in response to events
You may also subscribe the web browser directly to events. This is done by calling Jifty-
subs->add> with no region-relevant arguments, merely the topic
:
Jifty->subs->add( topic => $_ ) for qw/ some_event other_event /;
Once the browser is subscribed, the events will be made available via the global pubsub
object in javascript, and can be consumed via bind
:
jQuery(pubsub).bind("message.some_event", function (event, data) {
alert(data.some_key);
}
Sending messages from javascript
From javascript in the client, you may also send information back to the server via the global pubsub
object:
pubsub.send({type: 'something', data: 'here'}});
In order to act on these responses, create a YourApp::PubSub
which inherits from Jifty::Plugin::PubSub::Connection, and override "receive" in Jifty::Plugin::PubSub::Connection:
package YourApp::PubSub;
use base qw/ Jifty::Plugin::PubSub::Connection /;
sub receive {
my $self = shift;
my $msg = shift;
return 1 if $self->SUPER::receive( $msg );
warn "Got some message from the client: " . $msg->{data};
return 1;
}
Note that, for security reasons, this communication from the web browser is not published to the Jifty event bus (though you may opt to republish them there so manually).
METHODS
init
When initializing the plugin, it accepts any arguments that "new_with_traits" in AnyMQ accepts.
new_request
Part of the Jifty::Plugin interface; clears out the Jifty::Plugin::PubSub::Subscriptions on every request.
body_end
Part of the Jifty::Plugin interface; appends a snippet of javascript to start the client-side websocket.
psgi_app_static
Part of the Jifty::Plugin interface; provides the required static javascript.
wrap
Part of the Jifty::Plugin interface; wraps the application to provide websocket support, via Web::Hippie, and binds it to the AnyMQ bus via Web::Hippie::Pipe.