The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Module::API

WARNING

This code is still being developed. It is subject to change at any moment. It is only being made available at this time to solicit comments on it. If you see something you want changed please let me know.

SYNOPSIS

In file MyModule::API.pm:

    package MyAPI;
    use base 'Module::API';

    sub init {
      $self = shift;
      $self->api_server( 'http://my.server.com/api-listner' );
    }

In some other code:

    use MyAPI;
    my $api = MyAPI->new;

    # Send an API request to be handled on the remote server by a
    # plugin under 'MyAPI::Handler::...';
    my $response = $api->send( 'request_name', $payload_hashref );

METHODS

new

    $api = Module::API->new;

Get a new api object that is used to send and recieve the Module::API requests. Can also be used to set settings at start up:

    $api = Module::API->new(
        token    => 'abcdefghijklmnopqrst',
        server_url   => 'http://api.example.com/api',
        encoding => 'xml',
    );

init

    package MyAPI;
    use base 'Module::API';

    sub init {
        my $self = shift;

        my $token = load_token_from_file_or_something();
        $self->config( 'token', $token );

        return 1;
    }

init is a method that you should override to initure your API object. It is called by new after the object has been created and the values passed in have been assigned. After it has returned set_defaults is called.

set_defaults

    $api->set_defaults;

Looks at what the current settings are and then changes other settings that are not set to the correct defaults:

    token    => ''
    server_url       => ''
    encoding => 'storable'

Module::API requests

There are three ways in which the API requests can be handled - locally, remotely and non-blocking remotely:

local requests

    $api->api_server( '' );
    $response = $api->send( 'request_name', \%payload );

Local requests are made to handlers on the local machine. This happens by default if api_server is an empty string. The advantage to local requests is the low overhead as that there is no encoding or decoding or the payload.

remote requests

    $api->api_server( 'http://api.exampe.com/api-listener' );
    $response = $api->send( 'request_name', \%data );

Remote requests are done over the network to a remote machine that is listening for them. The response is returned when it is available.

non-blocking remote requests

    $api->api_server('http://api.exampe.com/api-listener');
    $api->queue->add( 'request_name_1', \%payload_1 );
    $api->queue->add( 'request_name_2', \%payload_2 );

    while ( $api->queue->requests_queued ) {

        # check if a request has been completed
        if ( my $response = $api->queue->get_a_ready_response ) {

            # deal with the returned payload
            ...;
            next;
        }

        # do something whilst the requests are processed.
        ...;
    }

The problem with the remote request made using $api-do()> is that it is blocking - control is not returned to the code until the response has been returned. In many sitations this will not be a problem but if you are writing an application that is interactive or that needs to make several requests in parallel then this is not ideal - especially if the API requests take a long time.

In cases like this you will want to use the request queue - see Module::API::Queue for more details. In summary you create requests that are added to the queue. These requests are then added to an IO::Select object which is then managed. All of this is abstracted from you so you need only add the requests and occasionally check if any have completed and then process them.

CAVEAT: Some planning may be required as the order that the responses will be returned in is not the order in which they are made. If you make one slow request and then a fast one you will most likely get the fast response back first. As the original request is available in the response you will be able to work out what to do.

create_request

    $api_request = $api->create_request(
        request_name => $request_name,
    );

Creates a request. Settings are taken from the $api object if they are not specified as arguments. Gennerally you will want to use the calling form $api-request_name> mentioned above though unless you really want access to the request object.

request_from_params

    $api_request = $api->request_from_params( \%params );

encoders

    @module_names = $api->encoders;

Returns a list of encoders that can be used.

get_encoder

  $encoder_name = $api->get_encoder( 'encoding-name' );

Returns the first encoder to match the encoding given.

server

  my $server = $api->server;

Returns a Module::API::Server object that can accept and process the API calls of $api. Creates the server if needed.

queue

    my $api_queue = $api->queue;

Creates if needed a queue and returns it. See Module::API::Queue for more details.