NAME

POEx::ProxySession::Client - Proxies remote, published Sessions, or publishes, local Sessions for subscription

VERSION

version 1.102760

SYNOPSIS

    # on the publisher side
    class Foo 
    {
        with 'POEx::Role::SessionInstantiation';
        use aliased 'POEx::Role::Event';
        use aliased 'POEx::Role::ProxyEvent';
        
        # The event we want to expose
        method yarg() {  } is ProxyEvent
        
        after _start(@args) is Event
        {
            POEx::ProxySession::Client->new
            ( 
                alias   => 'Client',
                options => { trace => 1, debug => 1 },
            );

            $self->post
            (
                'Client', 
                'connect', 
                remote_address  => '127.0.0.1', 
                remote_port     => 56789,
                return_event    => 'post_connect'
            );
        }

        method post_connect
        (
            WheelID :$connection_id, 
            Str :$remote_address, 
            Int :$remote_port
        ) is Event
        {
            $self->post
            (
                'Client',
                'publish',
                connection_id   => $connection_id,
                session_alias   => 'FooSession',
                session         => $self,
                return_event    => 'check_publish'
            );
        }

        .....
    }

    # on the subscriber side
    class Bar with POEx::Role::SessionInstantiation
    {
        use aliased 'POEx::Role::Event';
        use aliased 'POEx::Role::ProxyEvent';
        
        after _start(@args) is Event
        {
            POEx::ProxySession::Client->new
            ( 
                alias   => 'Client',
                options => { trace => 1, debug => 1 },
            );

            $self->post
            (
                'Client', 
                'connect', 
                remote_address  => '127.0.0.1', 
                remote_port     => 56789,
                return_event    => 'post_connect'
            );
        }

        method post_connect
        (
            WheelID :$connection_id, 
            Str :$remote_address, 
            Int :$remote_port
        ) is Event
        {
            $self->post
            (
                'Client',
                'subscribe',
                connection_id   => $connection_id,
                to_session      => 'FooSession',
                return_event    => 'post_subscription',
            );
        }
        
        method post_subscription(Bool :$success, Str :$session_name, Ref :$payload?) is Event
        {
            if($success)
            {
                $self->post('FooSession', 'yarg');
            }
        }
    }

DESCRIPTION

POEx::ProxySession::Client enables remote sessions to interact with one another via a system of subscription and publication. Client works via introspection on Moose::Meta::Classes to build local, persistent sessions that proxy posts back to the publisher with the attendant method signatures.

PUBLIC_ATTRIBUTES

subscriptions

This attribute is used to store the various subscriptions made through the client. It has no accessors beyond what are defined in the provides mechanism.

    handles     => 
    {
        get_subscription        => 'get',
        set_subscription        => 'set',
        delete_subscription     => 'delete',
        count_subscriptions     => 'count',
        all_subscription_names  => 'keys',
        has_subscription        => 'exists',
    }

Each instance of a subscription is actually stored as a hash with the following keys:

    Subscription =>
    {
        meta    => isa Moose::Meta::Class,
        wheel   => isa WheelID
    }

active_connectios

The clients active connects are stored in this attribute. The following methods are provided to access them:

    handles     => 
    {
        get_active_connection        => 'get',
        set_active_connection        => 'set',
        delete_active_connection     => 'delete',
        count_active_connections     => 'count',
        all_active_connection_ids    => 'keys',
        has_active_connection        => 'exists',
    }

Each connection is represented by a hashref with the following keys:

    Connection =>
    {
        remote_address  => isa Str,
        remote_port     => isa Int,
        tag             => isa Optional[Ref],
    }

unknown_message_event

    is: 'rw', isa: Tuple[SessionID|SessionAlias, Str]

Set this attribute to receive unknown messages that were sent to the client. This is handy for sending custom message types across the Server.

The event handler must have this signature: (ProxyMessage $data, WheelID $id)

socket_error_event

    is: 'rw', isa: Tuple[SessionID|SessionAlias, Str]

When a socket error is received, the wheel is cleared, and the connection hash is deleted from the active connection structure. Set this attribute to be notified when a socket error occurs.

The event handler must have this signature: (Str :$remote_address, Int :$remote_port, Ref :$tag?)

connect_error_event

    is: 'rw', isa: Tuple[SessionID|SessionAlias, Str]

When a connect error is received, the wheel is cleared, and the connection hash is deleted from the active connection structure. Set this attribute to be notified when a socket error occurs.

The event handler must have this signature: (Str :$remote_address, Int :$remote_port, Ref :$tag?)

PUBLIC_METHODS

subscribe

    (WheelID :$connection_id,
    SessionAlias :$to_session,
    SessionAlias|SessionID|Session|DoesSessionInstantiation :$return_session?,
    Str :$return_event,
    Ref :$tag?) is Event

subscribe sends a message out to the server, and the handler receives the appropriate metadata and constructs a local, persistent session that proxies posts back to the publisher. Once the session is finished constructing itself it will post a message to the provided return event.

The return event must have the following signature: (WheelID :$connection_id, Bool :$success, SessionAlias :$session_name, Ref :$payload, Ref :$tag?)

Since subscription can fail, $success will indicate whether it succeeded or not and if not $payload will be a scalar reference to a string explaining why.

Otherwise, if subscription was successful, $payload will contain the original payload from the server containing the metadata.

unsubscribe

    (SessionAlias :$session_name,
    SessionAlias|SessionID|Session|DoesSessionInstantiation :$return_session?,
    Str :$return_event,
    Ref :$tag) is Event

To unsubscribe from a proxied session, use this method. This will destroy the session by removing its alias. Only pending events will keep the session alive.

If it happens such that the session no longer exists, the return event will be posted right away, other wise, _stop on the proxied session is advised to post the return event.

The return event must have the following signature: (Bool :$success, SessionAlias :$session_alias, Ref :$tag?)

publish

    (WheelID :$connection_id,
    SessionAlias :$session_alias,
    DoesSessionInstantiation :$session,
    SessionAlias|SessionID|Session|DoesSessionInstantiation :$return_session?,
    Str :$return_event,
    Ref :$tag?) is Event

This method will publish a particular session to the server, such that other clients can then subscribe.

The connection_id is required to know where to send the publish message. Keep track of each connection_id received from connect() to know where publications should happen. The session_alias argument is how the session should be addressed on the server. The alias will be used by subscribing clients.

Currently, only sessions that are composed of POEx::Role::SessionInstantiation are supported and as such, a reference to a session that does that role is required to allow the proper introspection on the subscriber end.

To indicate which methods should be proxied, simply decorate them with the POEx::Role::ProxyEvent role. All other methods will be ignored in proxy creation.

The return event must have the following signature: (WheelID :$connection_id, Bool :$success, SessionAlias :$session_alias, Ref :$payload?, Ref :$tag?)

Since publication can fail, $success will indicate whether it succeeded or not and if not $payload will be a scalar reference to a string explaining why.

Otherwise, if publication was successful, $payload will contain the original payload from the server containing the metadata.

rescind

    (DoesSessionInstantiation :$session,
    SessionAlias|SessionID|Session|DoesSessionInstantiation :$return_session?,
    Str :$return_event,
    Ref :$tag?) is Event

To take back a publication, use this method and pass it the session reference.

The return event must have the following signature: (WheelID :$connection_id, Bool :$success, SessionAlias :$session_name, Ref :$payload?, Ref :$tag?)

Since rescinding can fail, $success will let you know if it did. And if it did, $payload will be a reference a string explaining why. Otherwise, payload will be undef.

server_listing

    (WheelID :$connection_id,
    SessionAlias|SessionID|Session|DoesSessionInstantiation :$return_session?,
    Str :$return_event,
    Ref :$tag?) is Event

server_listing will query a particular server for a list of all published sessions that it knows about. It returns it as an array of session aliases suitable for subscription.

The return event must have the following signature: (WheelID :$connection_id, Bool :$success, ArrayRef :$payload, Ref :$tag?)

PROTECTED_METHODS

handle_inbound_data

    (ProxyMessage $data, WheelID $id) is Event

Our implementation of handle_inbound_data expects a ProxyMessage as data. Here is where the handling and routing of messages lives. Only handles two types of ProxyMessage: result, and deliver. For more information on ProxyMessage types, see the POD in POEx::ProxySession::Types. If an unknown message type is encountered and unknown_message_event is set, it will be delivered to there.

around connect

    (Str :$remote_address,
    Int :$remote_port,
    SessionAlias|SessionID|Session|DoesSessionInstantiation :$return_session?,
    Str :$return_event,
    Ref :$tag?) is Event

The connect method is advised to add additional parameters in the form of a return session and return event to use once the connection has been established.

The return event will need the following signature: (WheelID :$connection_id, Str :$remote_address, Int :$remote_port, Ref :tag?)

after handle_on_connect

    (GlobRef $socket, Str $address, Int $port, WheelID $id) is Event

handle_on_connect is advised to find the specified return session and event and post the message with the paramters received from the socketfactory

after handle_socket_error

    (Str $action, Int $code, Str $message, WheelID $id) is Event

handle_socket_error is advised to clean up the active connection if an error has occurred. The socket_error_event is delivered then with the connection information if there is such an event.

after handle_connect_error

    (Str $action, Int $code, Str $message, WheelID $id) is Event

handle_connect_error is advised to clean up resources such as the socket factory and the connection tag if there was a error connecting. The error along with the tag information is delivered to the connect_error_event if it has been defined.

PRIVATE_METHODS

after _start

    (@args) is Event

The _start method is advised to hardcode the filter to use as a POE::Filter::Reference instance.

=attrbute_public publications

This attribute is used to store all publications made through the client. It has no accessors beyond what are defined in the provides mechanism.

Each instance of a publication is stored as a hash with the following keys:

    Publication =>
    {
        methods         => isa HashRef,
        wheel           => isa WheelID,
        session_alias   => isa SessionAlias,
    }

CAVEATS

It should be noted that the transport mechanism makes use of Storable. That means that all of the various end points in a spawling system need to use the same version of Storable to make sure things serialize/deserialize correctly.

AUTHOR

Nicholas Perez <nperez@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2010 by Nicholas Perez.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.