AtteanX-Query-Cache

 view release on metacpan or  search on metacpan

lib/AtteanX/Query/AccessPlan/Cache.pm  view on Meta::CPAN

use 5.010001;
use strict;
use warnings;
use feature "state";

package AtteanX::Query::AccessPlan::Cache;
use Class::Method::Modifiers;

our $AUTHORITY = 'cpan:KJETILK';
our $VERSION   = '0.002';

use Moo::Role;
use Carp;

with 'MooX::Log::Any';

around 'access_plans' => sub {
	my $orig = shift;
	my @params = @_;
	my $self	= shift;
	my $model = shift;
	my $active_graphs	= shift;
	my $pattern	= shift;

	# First, add any plans coming from the original planner (which will
	# include queries to the remote SPARQL endpoint
	my @plans = $orig->(@params);
	my @vars	= $pattern->values_consuming_role('Attean::API::Variable');
	my @varstrings = map { $_->value } @vars;

	# Start checking the cache
	my $keypattern = $pattern->canonicalize->tuples_string;
	my $cached = $model->cache->get($keypattern);
	if (defined($cached)) {
		$self->log->info("Found data in the cache for " . $keypattern);
		my $parser = Attean->get_parser('NTriples')->new(lazy_iris => 1);
		my $iter;
		my $size = 0;
		if (ref($cached) eq 'ARRAY') {
			$size = scalar @{$cached};
			# Then, the cache resulted from a TP with just one variable
			$iter = Attean::CodeIterator->new(
														 generator => sub {
															 state $i = 0;
															 return undef if ($i > $#{$cached});
															 my $term = $parser->parse_term_from_string(${$cached}[$i]);
															 $i++;
															 return Attean::Result->new(bindings => { $vars[0]->value => $term });
														 },
														 item_type => 'Attean::API::Result',
														 variables => \@varstrings
														);
		} elsif (ref($cached) eq 'HASH') {
			# Cache resulted from TP with two variables
			my @firsts = keys(%{$cached});
			$size = scalar @firsts;
			$iter = Attean::CodeIterator->new(
														 generator => sub {
															 state $i = 0;
															 return undef if ($i > $#firsts);
															 state $j = 0;
															 my $term1 = $parser->parse_term_from_string($firsts[$i]);
															 my @seconds = @{${$cached}{$firsts[$i]}};
															 my $term2 = $parser->parse_term_from_string($seconds[$j]);
															 $j++;
															 if ($j > $#seconds) {
																 $j = 0;
																	 $i++;
															 }
															 return Attean::Result->new(bindings => {$vars[0]->value => $term1,
																												  $vars[1]->value => $term2});
														 },
														 item_type => 'Attean::API::Result',
														 variables => \@varstrings
														);
		} else {
			croak 'Unknown data structure found in cache for key ' . $keypattern;
		}
		push(@plans, Attean::Plan::Iterator->new( variables => \@vars,
																iterator => $iter,
																size_estimate => $size,
																distinct => 0,
																ordered => [] ));
	} else {
		$self->log->debug("Found no data in the cache for " . $keypattern);
	}



( run in 0.959 second using v1.01-cache-2.11-cpan-39bf76dae61 )