Bio-BioVeL
view release on metacpan or search on metacpan
Examples/Nexus_MultiplePartitions.nex
Examples/Nexus_SimplePartition.nex
Examples/TaxaDataExample.nex
Examples/TaxaMetadataExample.json
Examples/TaxaMetadataExample.tsv
Examples/TaxaTreeExample.dnd
Examples/treebase-record.xml
Examples/TreeMetadata.tsv
Examples/TreesExample.xml
lib/Bio/BioVeL.pm
lib/Bio/BioVeL/AsynchronousService.pm
lib/Bio/BioVeL/AsynchronousService/Mock.pm
lib/Bio/BioVeL/AsynchronousService/TNRS.pm
lib/Bio/BioVeL/Service.pm
lib/Bio/BioVeL/Service/NeXMLExtractor.pm
lib/Bio/BioVeL/Service/NeXMLMerger.pm
lib/Bio/BioVeL/Service/NeXMLMerger/CharSetReader.pm
lib/Bio/BioVeL/Service/NeXMLMerger/CharSetReader/nexus.pm
lib/Bio/BioVeL/Service/NeXMLMerger/CharSetReader/text.pm
lib/Bio/BioVeL/Service/NeXMLMerger/DataReader.pm
lib/Bio/BioVeL/Service/NeXMLMerger/DataReader/fasta.pm
lib/Bio/BioVeL/Service/NeXMLMerger/DataReader/nexus.pm
lib/Bio/BioVeL/Service/NeXMLMerger/DataReader/phylip.pm
`metaformat={tsv|JSON|csv}`, `charsetformat={txt}`
Output
------
* A subset of the NeXML data in the requested format, with a separate download of the
metadata, likewise in the requested format.
Service deployment
==================
We deploy the services as [mod_perl](http://perl.apache.org) handlers, which means that for
synchronous services (i.e. everything is done in one request/response cycle) no forking is
done at all. For asynchronous servers, the service class doesn't have to keep track of its
session: the superclass keeps track of serializing and de-serializing the job object
between requests.
Links
=====
* [Naturalis BioVeL github repo](https://github.com/naturalis/biovel-nbc)
* [BioVeL](http://biovel.eu)
* [BiodiversityCatalogue](http://biodiversitycatalogue.org)
* [NeXML](http://nexml.org)
* [Taverna](http://taverna.org.uk)
lib/Bio/BioVeL/AsynchronousService.pm view on Meta::CPAN
package Bio::BioVeL::AsynchronousService;
use strict;
use warnings;
use File::Path 'make_path';
use Scalar::Util 'refaddr';
use Bio::BioVeL::Service;
use Digest::MD5 'md5_hex';
use Apache2::Const '-compile' => qw'OK REDIRECT';
use Proc::ProcessTable;
use base 'Bio::BioVeL::Service';
# status constants
use constant RUNNING => 'running';
use constant DONE => 'done';
use constant ERROR => 'error';
=head1 NAME
Bio::BioVeL::AsynchronousService - base class for asynchronous web services
=head1 SYNOPSIS
use Bio::BioVeL::AsynchronousService::Mock; # example class
# this static method returns a writable directory into which
# service objects are persisted between request/response cycles
my $wd = Bio::BioVeL::AsynchronousService::Mock->workdir;
# when instantiating objects, values for the 'parameters' that are defined
# in their constructors can be provided as named arguments
my $mock = Bio::BioVeL::AsynchronousService::Mock->new( 'seconds' => 1 );
# every async service has a record of when it started
my $epoch_time = $mock->timestamp;
# can be RUNNING, ERROR or DONE
if ( $mock->status eq Bio::BioVeL::AsynchronousService::DONE ) {
print $mock->response_body;
}
=head1 DESCRIPTION
Asynchronous services need to subclass this class and implement at least the following
methods: C<launch> and C<response_body>. The parent class makes sure that launch()
forks off a process and returns immediately with enough information, stored as object
properties, so that update() can check how things are going and update the status().
Once the status set to C<DONE>, C<response_body> is executed to generate the output.
Successful implementations are likely going to have simple, serializable object properties
that allow a newly de-serialized object (i.e. during the next polling cycle) to probe
the process table or the job directory to check the status.
=head1 METHODS
lib/Bio/BioVeL/AsynchronousService/Mock.pm view on Meta::CPAN
package Bio::BioVeL::AsynchronousService::Mock;
use strict;
use warnings;
use Bio::BioVeL::AsynchronousService;
use base 'Bio::BioVeL::AsynchronousService';
=head1 NAME
Bio::BioVeL::AsynchronousService::Mock - example asynchronous service
=head1 DESCRIPTION
This dummy service runs the 'sleep' shell command for the provided number
of seconds, then returns with a simple text message.
=head1 METHODS
=over
lib/Bio/BioVeL/AsynchronousService/Mock.pm view on Meta::CPAN
the service should sleep for.
=cut
sub new {
shift->SUPER::new( 'parameters' => [ 'seconds' ], @_ );
}
=item launch
Runs the shell's C<sleep> command to demonstrate asynchronous operation.
Updates the status as needed to indicate success or failure.
=cut
sub launch {
my $self = shift;
if ( system("sleep", ( $self->seconds || 2 ) ) ) {
$self->status( Bio::BioVeL::AsynchronousService::ERROR );
$self->lasterr( $? );
}
else {
$self->status( Bio::BioVeL::AsynchronousService::DONE );
}
}
=item response_body
Returns a simple text string that specifies how long the process has slept for.
=cut
sub response_body { "I slept for ".shift->seconds." seconds" }
lib/Bio/BioVeL/AsynchronousService/TNRS.pm view on Meta::CPAN
package Bio::BioVeL::AsynchronousService::TNRS;
use strict;
use warnings;
use Bio::BioVeL::AsynchronousService;
use base 'Bio::BioVeL::AsynchronousService';
=head1 NAME
Bio::BioVeL::AsynchronousService::TNRS - wrapper for the SUPERSMART TNRS service
=head1 DESCRIPTION
B<NOTE>: this service is untested, it is a work in progress. It is meant to show
how the scripts of the L<http://www.supersmart-project.org> could be executed as
asynchronous web services.
=head1 METHODS
=over
=item new
The constructor specifies one object property: the location of the input C<names>
list.
lib/Bio/BioVeL/AsynchronousService/TNRS.pm view on Meta::CPAN
# SUPERSMART_HOME needs to be known and accessible to the httpd process
my $script = $ENV{'SUPERSMART_HOME'} . '/script/supersmart/mpi_write_taxa_table.pl';
# fetch the input file
my $readfh = $self->open_handle( $self->names );
open my $writefh, '>', $infile;
print $writefh $_ while <$readfh>;
# run the job
if ( system( $script, '-i' => $infile, ">$outfile", "2>$logfile" ) ) {
$self->status( Bio::BioVeL::AsynchronousService::ERROR );
$self->lasterr( $? );
}
else {
$self->status( Bio::BioVeL::AsynchronousService::DONE );
}
}
=item response_location
B<NOTE>: this is an untested feature. The idea is that child classes can re-direct
the client to an alternate location with, e.g. the most important output file or a
directory listing of files.
=cut
lib/Bio/BioVeL/Service.pm view on Meta::CPAN
'-level' => INFO,
'-class' => [
'Bio::BioVeL::Service::NeXMLMerger',
'Bio::BioVeL::Service::NeXMLExtractor'
]
);
our $AUTOLOAD;
=head1 NAME
Bio::BioVeL::Service - base class for synchronous web services
=head1 DESCRIPTION
The BioVeL API makes a distinction between "synchronised" and "asynchronous" services.
Synchronised services produce their final result within a single HTTP request/response
cycle by generating a response_body that is returned to the client at the end of the
cycle. Asynchronous services produce a result at the end of a longer running, forked
process, which needs to be tracked between request/response cycles.
All concrete service classes need to inherit from either one of these service type
superclasses (L<Bio::BioVeL::Service> or L<Bio::BioVeL::AsynchronousService>) so that
all the bookkeeping (processing request parameters, managing forked processes) is
taken care of and the concrete child class only needs to worry about producing its
result.
=head1 METHODS
=over
=item new
#!/usr/bin/perl
use strict;
use warnings;
use File::Temp 'tempdir';
use Test::More 'no_plan';
use Scalar::Util 'looks_like_number';
BEGIN { use_ok('Bio::BioVeL::AsynchronousService::Mock') }
$ENV{'BIOVEL_HOME'} = tempdir( 'CLEANUP' => 1 );
# $TEMP/Bio/BioVeL/AsynchronousService/Mock
ok( -d Bio::BioVeL::AsynchronousService::Mock->workdir );
my $new = Bio::BioVeL::AsynchronousService::Mock->new( 'seconds' => 1 );
isa_ok( $new, 'Bio::BioVeL::AsynchronousService' );
ok( looks_like_number $new->timestamp );
ok( $new->status eq Bio::BioVeL::AsynchronousService::RUNNING );
( run in 0.730 second using v1.01-cache-2.11-cpan-0d8aa00de5b )