view release on metacpan or search on metacpan
examples/edw/Rest.pl view on Meta::CPAN
#
# Create a user specific Hook used to handle Analysis replies.
#
$h_setup{hook} = new API::Eulerian::EDW::Hook::Print();
my $peer = new API::Eulerian::EDW::Peer::Rest(\%h_setup);
my $status = $peer->request( $cmd );
if ( $status->error() ) {
$status->dump();
exit(1);
}
# Dump stages durations
$status->{ bench }->dump();
# Cancel the command
$peer->cancel();
examples/edw/Thin.pl view on Meta::CPAN
grid => '', # TODO
ip => '', # TODO
token => '', # TODO
);
my $status;
my $peer;
my $cmd;
# Read command from File
$status = Eulerian::File->read( $path );
if( $status->error() ) {
$status->dump();
} else {
# Get command from file
$cmd = $status->{ data };
# Create Peer instance
$peer = new API::Eulerian::EDW::Peer( \%setup );
# Send Command, call hook
$status = $peer->request( $cmd );
if( $status->error() ) {
$status->dump();
} else {
# Dump stages durations
$status->{ bench }->dump();
# Cancel the command
$peer->cancel();
}
}
lib/API/Eulerian/EDW.pm view on Meta::CPAN
my ($self, $rh_p, $query) = @_;
$rh_p ||= {};
$rh_p->{accept} = 'text/csv';
$rh_p->{hook} = 'API::Eulerian::EDW::Hook::Noop';
$query ||= '';
my $peer = new API::Eulerian::EDW::Peer::Rest( $rh_p );
if ( !defined $peer ) {
return { error => 1, error_msg => 'unable to build object' };
}
my $status = $peer->request( $query );
if ( $status->error() ) {
return {
error => 1,
error_msg => $status->msg()
};
}
# kill request at EDW for clean-up
$peer->cancel();
return { error => 0, path2file => $status->path() };
}
1;
__END__
lib/API/Eulerian/EDW/Authority.pm view on Meta::CPAN
sub bearer
{
my ( $class, $kind, $platform, $grid, $ip, $token ) = @_;
my $response;
my $status;
my $code;
my $json;
# Get URL used to request API::Eulerian::EDW Authority for Token.
$status = $class->_url( $kind, $platform, $grid, $ip, $token );
# Handle errors
if( ! $status->error() ) {
# Request API::Eulerian::EDW Authority
$status = API::Eulerian::EDW::Request->get( $status->{ url } );
# Get HTTP response
$response = $status->{ response };
# Get HTTP response code
$code = $response->code;
# We expect JSON reply data
$json = API::Eulerian::EDW::Request->json( $response );
if( $json && ( $code == 200 ) ) {
$status = $json->{ error } ?
$class->_error( $code, $json->{ error_msg } ) :
$class->_success( $kind, $json );
} else {
$status = $class->_error(
$code, $json ?
encode_json( $json ) :
$response->decoded_content
);
}
}
return $status;
}
#
lib/API/Eulerian/EDW/Authority.pm view on Meta::CPAN
# @return API::Eulerian::EDW::Status
#
sub _url
{
my ( $class, $kind, $platform, $grid, $ip, $token ) = @_;
my $domain;
#
# Sanity check mandatories arguments
#
if( ! ( defined( $grid ) && length( $grid ) > 0 ) ) {
return $class->_error(
406, "Mandatory argument 'grid' is missing or invalid"
);
} elsif( ! ( defined( $ip ) && length( $ip ) > 0 ) ) {
return $class->_error(
406, "Mandatory argument 'ip' is missing"
);
} elsif( ! ( defined( $token ) && length( $token ) > 0 ) ) {
return $class->_error(
406, "Mandatory argument 'token' is missing"
);
}
#
# URL formats are :
#
# Start :
#
# https://<grid>.<domain>/ea/v2/<token>/er/account/
#
# Session token :
#
# <Start>get_dw_session_token.json?ip=<ip>&output-as-kv=1
#
# Access token :
#
# <Start>get_dw_access_token.json?ip=<ip>&output-as-kv=1
#
if( ! ( $kind = $KINDS{ $kind } ) ) {
return $class->_error( 406, "Invalid token kind : $kind" );
} elsif( ! ( $domain = $DOMAINS{ $platform } ) ) {
return $class->_error( 506, "Invalid platform : $platform" );
} else {
my $status = API::Eulerian::EDW::Status->new();
my $url;
$url = 'https://';
$url .= $grid . '.';
$url .= $domain . '/ea/v2/';
$url .= $token . $kind;
$url .= $ip . '&output-as-kv=1';
$status->{ url } = $url;
lib/API/Eulerian/EDW/Authority.pm view on Meta::CPAN
}
#
# @brief Return Error on API::Eulerian::EDW Authority Services.
#
# @param $class - API::Eulerian::EDW::Authority class.
# @param $code - HTTP Error code.
# @param $message - Error message.
#
# return API::Eulerian::EDW::Status
#
sub _error
{
my ( $class, $code, $message ) = @_;
my $status = API::Eulerian::EDW::Status->new();
$status->error( 1 );
$status->code( $code );
$status->msg( $message );
return $status;
}
#
# @brief Return Success on API::Eulerian::EDW Authority Services.
#
# @param $class - API::Eulerian::EDW::Authority class.
# @param $kind - Token kind.
# @param $json - Json reply.
lib/API/Eulerian/EDW/File.pm view on Meta::CPAN
# @return API::Eulerian::EDW::Status
#
sub read
{
my $status = API::Eulerian::EDW::Status->new();
my ( $class, $path ) = @_;
my $data;
my $fd;
# Open file for reading
open $fd, "<", $path or do {
$status->error( 1 );
$status->code( -1 );
$status->msg( "Opening file : $path for reading failed. $!" );
return $status;
};
# Read file content
$data = do { local $/; <$fd> };
# Close file
close $fd;
# Save content
$status->{ data } = $data;
lib/API/Eulerian/EDW/Hook/Print.pm view on Meta::CPAN
# @param $token - AES Token or Bearer.
# @param $errnum - Error number.
# @param $err - Error description.
# @param $updated - Count of updates on server.
#
sub on_status
{
my ( $self, $uuid, $token, $errnum, $err, $updated ) = @_;
# my $string = <<string_end;
# $uuid : {
# error_code => $errnum,
# error_msg => $err,
# }
#string_end
#print( $string );
return $self;
}
#
# Endup module properly
#
1;
lib/API/Eulerian/EDW/Peer.pm view on Meta::CPAN
if( ! defined( $bearer ) ) {
# Request Authority Services for a valid bearer
$status = API::Eulerian::EDW::Authority->bearer(
$self->kind(), $self->platform(),
$self->grid(), $self->ip(),
$self->token()
);
# Cache bearer value for next use
$self->{ _BEARER } = $status->{ bearer } if ! $status->error();
} else {
# Return Cached bearer value
$status = API::Eulerian::EDW::Status->new();
$status->{ bearer } = $bearer;
}
return $status;
}
#
# @brief Create HTTP Request Headers.
lib/API/Eulerian/EDW/Peer.pm view on Meta::CPAN
#
# @return API::Eulerian::EDW::Status. On success a new entry 'headers' is inserted into
# the status.
#
sub headers
{
my $self = shift;
my $status = $self->_bearer();
my $headers;
if( ! $status->error() ) {
# Create a new Object Headers
$headers = API::Eulerian::EDW::Request->headers();
# Setup Authorization Header value
$headers->push_header( 'Authorization', $status->{ bearer } );
# Setup reply context
$status->{ headers } = $headers;
# Remove bearer
delete $status->{ bearer };
}
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
# @param $self - Eulerian Data Warehouse Peer.
#
# @return HTTP Headers.
#
sub headers
{
my $self = shift;
my $status = $self->SUPER::headers();
my $headers;
if( ! $status->error() ) {
$headers = $status->{ headers };
$headers->push_header( 'Content-Type', 'application/json' );
$headers->push_header( 'Accept', $self->accept() );
$headers->push_header( 'Accept-Encoding', $self->encoding() );
}
return $status;
}
#
# @brief Create a new JOB on Eulerian Data Warehouse Rest Platform.
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
# @return Reply content.
#
sub create
{
my ( $self, $command ) = @_;
my $response;
my $status;
# Create headers
$status = $self->headers();
if( ! $status->error() ) {
my $url = $self->url() . '/edw/jobs';
# Post Job create request to remote host
$status = API::Eulerian::EDW::Request->post(
$url, $status->{ headers }, $self->body( $command )
);
if( ! $status->error() ) {
$self->uuid(
API::Eulerian::EDW::Request->json(
$status->{ response }
)->{ data }->[ 0 ]
);
}
}
return $status;
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
# @return Job Reply status.
#
sub status
{
my ( $self, $status ) = @_;
my $response = $status->{ response };
my $url = API::Eulerian::EDW::Request->json(
$response )->{ data }->[ 1 ];
$status = $self->headers();
if( ! $status->error() ) {
$status = API::Eulerian::EDW::Request->get(
$url, $status->{ headers }
);
}
return $status;
}
#
# @brief Test if Job status is 'Running';
#
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
#
# @param $self - API::Eulerian::EDW::Rest instance.
# @param $rc - Return context.
#
# @return 0 - Not Done.
# @return 1 - Done.
#
sub done
{
my ( $self, $status ) = @_;
return ! $status->{ error } ?
API::Eulerian::EDW::Request->json(
$status->{ response }
)->{ status } eq 'Done' :
0;
}
#
# @brief Get Path to local filepath.
#
# @param $self - API::Eulerian::EDW::Rest instance.
#
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
my ( $self, $response ) = @_;
my $encoding = $self->encoding();
my $json = API::Eulerian::EDW::Request->json( $response );
my $pattern = '([0-9]*)\.(json|csv|parquet)';
my $status = API::Eulerian::EDW::Status->new();
my $url = $json->{ data }->[ 1 ];
my $wdir = $self->wdir();
my %rc = ();
if( ! $wdir ) {
$status->error( 1 );
$status->code( 400 );
$status->msg( "Working directory isn't set" );
} elsif( ! API::Eulerian::EDW::File->writable( $wdir ) ) {
$status->error( 1 );
$status->code( 400 );
$status->msg( "Working directory isn't writable" );
} elsif( ! ( $url =~ m/$pattern/ ) ) {
$status->error( 1 );
$status->code( 400 );
$status->msg( "Unknown local file name" );
} else {
my $path = $wdir. '/' . "$1.$2";
$status->{ url } = $url;
$status->{ path } = $path;
}
return $status;
}
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
#
# @return Reply context
#
sub download
{
my ( $self, $status ) = @_;
# From Last status message compute local file path
$status = $self->path( $status->{ response } );
# If no error
if( ! $status->{ error } ) {
my $path = $status->{ path };
my $url = $status->{ url };
my $response;
# Get HTTP request headers
$status = $self->headers();
if( ! $status->{ error } ) {
# Send Download request to remote host, reply is
# writen into $path file
$status = API::Eulerian::EDW::Request->get(
$url, $status->{ headers }, $path
);
# Handle errors
if( ! $status->error() ) {
my $encoding = $status->{ 'encoding' };
if( defined( $encoding ) && ( $encoding eq 'gzip' ) ) {
rename $path, "$path.gz";
$status->{ path } = $self->unzip( "$path.gz" );
} else {
$status->{ path } = $path;
}
} else {
print "ERROR : " . $status->{ _CODE } . "\n";
}
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
# Parse file path, get file type
if( ( $path =~ m/$pattern/ ) ) {
# Lookup for parser matching file type
if( ( $name = $PARSERS{ $1 } ) ) {
# Create new instance of Parser
if( ( $parser = $name->new( $path, $self->uuid() ) ) ) {
# Parse reply file raise callback hook
$parser->do( $self->hook() );
} else {
$status->error( 1 );
$status->msg( "Failed to create Parser" );
$status->code( 401 );
}
} else {
$status->error( 1 );
$status->msg( "Unknown Parser" );
$status->code( 501 );
}
} else {
$status->error( 1 );
$status->msg( "Unknown file format" );
$status->code( 401 );
}
return $status;
}
#
# @brief Do Request on Eulerian Data Warehouse Platform.
#
# @param $self - Eulerian Data Warehouse Peer.
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
my $status;
my $json;
# Create Job on Eulerian Data Warehouse Platform
$bench->start();
$status = $self->create( $command );
$bench->stage( 'create' );
# Wait end of Job
$bench->start();
while( ! $status->error() && $self->running( $status ) ) {
$status = $self->status( $status );
sleep( 2 );
}
$bench->stage( 'running' );
# If Done, download reply file
if( ! $status->error() && $self->done( $status ) ) {
$bench->start();
$status = $self->download( $status );
$bench->stage( 'download' );
if( ! $status->error() ) {
# Parse reply file, call hooks
$bench->start();
$status = $self->parse( $status );
$bench->stage( 'parse' );
}
$status->{ bench } = $bench;
} else {
print "ERROR : " . Dumper( $status ) . "\n";
}
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
# @param $self - API::Eulerian::EDW::Rest instance.
# @param $rc - Reply context.
#
sub cancel
{
my ( $self ) = @_;
my $status;
# Get HTTP request headers
$status = $self->headers();
if( ! $status->error() ) {
my $headers = $status->{ headers };
delete $status->{ headers };
# Create cancel job url
if( ! $self->uuid() ) {
$status->error( 1 );
$status->msg( "Failed to cancel Job. Unknown UUID" );
$status->code( 404 );
} else {
my $url = $self->url() . '/edw/jobs/';
$url .= $self->uuid() . '/cancel';
# Send Cancel request to remote host
$status = API::Eulerian::EDW::Request->get( $url, $headers );
}
lib/API/Eulerian/EDW/Peer/Rest.pm view on Meta::CPAN
# @param $from - Day begin.
# @param $end - Day end.
#
sub drop
{
my ( $self, $what, $site, $from, $to ) = @_;
my $status;
# Get HTTP request headers
$status = $self->headers();
if( ! $status->error() ) {
my $headers = $status->{ headers };
my $url = $self->url() . '/edw/store';
my $cmd = "DROP $what\@$site FROM $from TO $to;";
delete $status->{ headers };
# Send Cancel request to remote host
$status = API::Eulerian::EDW::Request->post(
$url, $headers, $self->body( $cmd )
);
}
lib/API/Eulerian/EDW/Peer/Thin.pm view on Meta::CPAN
#
use Data::Dumper;
sub create
{
my ( $self, $command ) = @_;
my $response;
my $status;
# Get Valid Headers
$status = $self->headers();
if( ! $status->error() ) {
# Post new JOB to Eulerian Data Warehouse Platform
$status = API::Eulerian::EDW::Request->post(
$self->url(), $status->{ headers }, $command, 'text/plain'
);
if( ! $status->error() ) {
my $json = API::Eulerian::EDW::Request->json( $status->{ response } );
if( defined( $json ) && $json->{ status }->[ 1 ] != 0 ) {
$status = API::Eulerian::EDW::Status->new();
$status->error( 1 );
$status->msg( $json->{ status }->[ 0 ] );
$status->code( $json->{ status }->[ 1 ] );
}
}
}
return $status;
}
#
# @brief Dispatch Eulerian Data Warehouse Analytics Analysis result messages to
lib/API/Eulerian/EDW/Peer/Thin.pm view on Meta::CPAN
my $bench = new API::Eulerian::EDW::Bench();
my $response;
my $status;
my $json;
# Create Job on Eulerian Data Warehouse Platform
$bench->start();
$status = $self->create( $command );
$bench->stage( 'create' );
if( ! $status->error() ) {
# Join Websocket call user specific callback hook
$bench->start();
$status = $self->join( $status );
$bench->stage( 'join' );
$status->{ bench } = $bench;
}
return $status;
}
#
lib/API/Eulerian/EDW/Peer/Thin.pm view on Meta::CPAN
# @param $self - API::Eulerian::EDW::Peer::Rest instance.
# @param $rc - Reply context.
#
sub cancel
{
my ( $self ) = @_;
my $status;
# Get Valid Headers
$status = $self->headers();
if( ! $status->error() && exists( $self->{ uuid } ) ) {
my $uuid = $self->{ uuid };
my $command = "KILL $uuid;";
# Post new JOB to Eulerian Data Warehouse Platform
$status = API::Eulerian::EDW::Request->post(
$self->url(), $status->{ headers }, $command, 'text/plain'
);
}
lib/API/Eulerian/EDW/Request.pm view on Meta::CPAN
my $status = API::Eulerian::EDW::Status->new();
my $endpoint;
my $request;
# Ensure default type
$type = $type || 'application/json';
# Sanity check POST arguments
if( $method eq 'POST' ) {
if( ! ( defined( $what ) && defined( $type ) ) ) {
$status->error( 1 );
$status->msg( "Mandatory argument to post request is/are missing" );
$status->code( 400 );
return $status;
} else {
# Setup Content_Length and Content_Type
$headers->push_header( Content_Length => length( $what ) );
$headers->push_header( Content_Type => $type );
}
}
lib/API/Eulerian/EDW/Request.pm view on Meta::CPAN
$endpoint->timeout( 1800 );
# Send Request, wait response if file is defined reply content is
# writen into local file.
my $response = $endpoint->request( $request, $file );
my $json = API::Eulerian::EDW::Request->json( $response );
$status->{ response } = $response;
if( $response->code != HTTP_OK ) {
$status->error( 1 );
$status->code( $response->code );
$status->msg(
defined( $json ) ?
encode_json( $json ) : $response->content()
);
} else {
if( defined( $response->header( 'content-encoding' ) ) ) {
$status->{ encoding } = $response->header( 'content-encoding' );
}
}
lib/API/Eulerian/EDW/Status.pm view on Meta::CPAN
#/usr/bin/env perl
###############################################################################
#
# @file Status.pm
#
# @brief API::Eulerian::EDW Status used to return function error to the callers
#
# @author Thorillon Xavier:x.thorillon@eulerian.com
#
# @date 25/11/2021
#
# @version 1.0
#
###############################################################################
#
# Setup perl package name
lib/API/Eulerian/EDW/Status.pm view on Meta::CPAN
{
my ( $class ) = @_;
return bless( {
_ERROR => 0,
_MSG => '',
_CODE => 0,
}, $class
);
}
#
# @brief Get/Set error message.
#
# @param $self - API::Eulerian::EDW::Status instance.
# @param $msg - Error message.
#
# @return Error message.
#
sub msg
{
my ( $self, $msg ) = @_;
$self->{ _MSG } = $msg if defined( $msg );
return $self->{ _MSG };
}
#
# @brief Get/Set error code.
#
# @param $self - API::Eulerian::EDW::Status instance.
# @param $code - Error code.
#
# @return Error code.
#
sub code
{
my ( $self, $code ) = @_;
$self->{ _CODE } = $code if defined( $code );
return $self->{ _CODE };
}
#
# @brief Get/Set error.
#
# @param $self - API::Eulerian::EDW::Status instance.
# @param $error - Error.
#
# @return Error flag.
#
sub error
{
my ( $self, $error ) = @_;
$self->{ _ERROR } = $error if defined( $error );
return $self->{ _ERROR };
}
sub path
{
my $self = shift;
return $self->{ path };
}
#
# @brief Dump status.
#
# @param $self - API::Eulerian::EDW::Status.
#
sub dump
{
my ( $self ) = @_;
my $error = $self->error() ? 'Yes' : 'No';
my $code = $self->code();
my $msg = $self->msg();
my $string = <<string_end;
Error : $error
Code : $code
Message : $msg
string_end
print( $string );
}
#
# End up perl module properly
#
1;
lib/API/Eulerian/EDW/Status.pm view on Meta::CPAN
I<Create a new API::Eulerian::EDW::Status instance.>
=head3 output
=over 4
=item * Instance of an API::Eulerian::EDW::Status.
=back
=head2 error()
I<Get/Set error flag.>
=head3 input
=over 4
=item * [optional] Error flag.
=back
=head3 output
lib/API/Eulerian/EDW/WebSocket.pm view on Meta::CPAN
#
# @return
#
sub _on_read
{
my ( $peer, $buf ) = @_;
my $ws = $peer->{ _WS };
$ws->{ _HOOK }( $ws, $buf );
}
#
# @brief On error Websocket handler.
#
# @param $self - Websocket.
#
# @return
#
sub _on_error
{
my ( $self, $error ) = @_;
print STDERR "Websocket error : $error\n";
}
#
# @brief On connect Websocket handler.
#
# @param $self - Websocket.
#
# @return
#
sub _on_connect
{
lib/API/Eulerian/EDW/WebSocket.pm view on Meta::CPAN
# Create a Websocket
$peer = Protocol::WebSocket::Client->new(
url => $url,
max_payload_size => $bufsize
);
# Setup Websocket hooks
$peer->on( write => \&API::Eulerian::EDW::WebSocket::_on_write );
$peer->on( read => \&API::Eulerian::EDW::WebSocket::_on_read );
$peer->on( error => \&API::Eulerian::EDW::WebSocket::_on_error );
$peer->on( connect => \&API::Eulerian::EDW::WebSocket::_on_connect );
# Save back refs
$self->{ _HOOK } = $hook;
$peer->{ _WS } = $self;
# Connect on remote host
$peer->connect;
# If connected