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.