API-Eulerian

 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



( run in 0.401 second using v1.01-cache-2.11-cpan-65fba6d93b7 )