Skip to content

Commit a24a39d

Browse files
committed
Added new /reverse_dependencies API endpoints
Added 2 new endpoints: * /reverse_dependencies/dist/DISTRIBUTION moved query from WEB * /reverse_dependencies/module/MODULE copied (& later will remove) current /release/requires endpoint Added a new controller Controller/ReverseDependencies.pm to later replace the current Controller/Search/ReverseDependencies.pm (will be removed with all supporting code once WEB is set to point to new endpoints)
1 parent 544c64b commit a24a39d

File tree

3 files changed

+192
-44
lines changed

3 files changed

+192
-44
lines changed

lib/MetaCPAN/Document/Release.pm

Lines changed: 162 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -551,50 +551,6 @@ sub get_files {
551551
return { files => [ map { $_->{_source} } @{ $ret->{hits}{hits} } ] };
552552
}
553553

554-
sub requires {
555-
my ( $self, $module, $page, $page_size, $sort ) = @_;
556-
$page //= 1;
557-
$page_size //= 20;
558-
$sort //= { date => 'desc' };
559-
560-
my $query = {
561-
query => {
562-
filtered => {
563-
query => { 'match_all' => {} },
564-
filter => {
565-
and => [
566-
{ term => { 'status' => 'latest' } },
567-
{ term => { 'authorized' => 1 } },
568-
{
569-
term => {
570-
'dependency.module' => $module
571-
}
572-
}
573-
]
574-
}
575-
}
576-
}
577-
};
578-
579-
my $ret = $self->es->search(
580-
index => $self->index->name,
581-
type => 'release',
582-
body => {
583-
query => $query,
584-
from => $page * $page_size - $page_size,
585-
size => $page_size,
586-
sort => [$sort],
587-
}
588-
);
589-
return {} unless $ret->{hits}{total};
590-
591-
return +{
592-
data => [ map { $_->{_source} } @{ $ret->{hits}{hits} } ],
593-
total => $ret->{hits}{total},
594-
took => $ret->{took}
595-
};
596-
}
597-
598554
sub _activity_filters {
599555
my ( $self, $params, $start ) = @_;
600556
my ( $author, $distribution, $module, $new_dists )
@@ -795,5 +751,167 @@ sub top_uploaders {
795751
};
796752
}
797753

754+
sub requires {
755+
my ( $self, $module, $page, $page_size, $sort ) = @_;
756+
$page //= 1;
757+
$page_size //= 20;
758+
$sort //= { date => 'desc' };
759+
760+
my $query = {
761+
query => {
762+
filtered => {
763+
query => { 'match_all' => {} },
764+
filter => {
765+
and => [
766+
{ term => { 'status' => 'latest' } },
767+
{ term => { 'authorized' => 1 } },
768+
{
769+
term => {
770+
'dependency.module' => $module
771+
}
772+
}
773+
]
774+
}
775+
}
776+
}
777+
};
778+
779+
my $ret = $self->es->search(
780+
index => $self->index->name,
781+
type => 'release',
782+
body => {
783+
query => $query,
784+
from => $page * $page_size - $page_size,
785+
size => $page_size,
786+
sort => [$sort],
787+
}
788+
);
789+
return {} unless $ret->{hits}{total};
790+
791+
return +{
792+
data => [ map { $_->{_source} } @{ $ret->{hits}{hits} } ],
793+
total => $ret->{hits}{total},
794+
took => $ret->{took}
795+
};
796+
}
797+
798+
sub reverse_dependencies {
799+
my ( $self, $distribution, $page, $page_size, $sort ) = @_;
800+
801+
# get the latest release of given distribution
802+
my $release = $self->_get_latest_release($distribution) || return;
803+
804+
# get (authorized/indexed) modules provided by the release
805+
my $modules = $self->_get_provided_modules($release) || return;
806+
807+
# get releases depended on those modules
808+
my $depended
809+
= $self->_get_depended_releases( $modules, $page, $page_size, $sort )
810+
|| return;
811+
812+
my $data = [ map [ @{$_}{qw( name author date )} ], @{$depended} ];
813+
single_valued_arrayref_to_scalar($data);
814+
return +{ data => $data };
815+
}
816+
817+
sub _get_latest_release {
818+
my ( $self, $distribution ) = @_;
819+
820+
my $release = $self->es->search(
821+
index => $self->index->name,
822+
type => 'release',
823+
body => {
824+
query => {
825+
bool => {
826+
must => [
827+
{ term => { distribution => $distribution } },
828+
{ term => { status => 'latest' } },
829+
{ term => { authorized => 1 } },
830+
]
831+
},
832+
},
833+
fields => [qw< name author >],
834+
},
835+
);
836+
return unless $release->{hits}{total};
837+
838+
my ($release_info) = map { $_->{fields} } @{ $release->{hits}{hits} };
839+
single_valued_arrayref_to_scalar($release_info);
840+
841+
return +{
842+
name => $release_info->{name},
843+
author => $release_info->{author},
844+
};
845+
}
846+
847+
sub _get_provided_modules {
848+
my ( $self, $release ) = @_;
849+
850+
my $provided_modules = $self->es->search(
851+
index => $self->index->name,
852+
type => 'file',
853+
body => {
854+
query => {
855+
bool => {
856+
must => [
857+
{ term => { 'release' => $release->{name} } },
858+
{ term => { 'author' => $release->{author} } },
859+
{ term => { 'module.authorized' => 1 } },
860+
{ term => { 'module.indexed' => 1 } },
861+
]
862+
}
863+
},
864+
size => 999,
865+
}
866+
);
867+
return unless $provided_modules->{hits}{total};
868+
869+
return [
870+
map { $_->{name} }
871+
grep { $_->{indexed} && $_->{authorized} }
872+
map { @{ $_->{_source}{module} } }
873+
@{ $provided_modules->{hits}{hits} }
874+
];
875+
}
876+
877+
sub _get_depended_releases {
878+
my ( $self, $modules, $page, $page_size, $sort ) = @_;
879+
$sort //= { date => 'desc' };
880+
$page //= 1;
881+
$page_size //= 50;
882+
883+
# because 'terms' doesn't work properly
884+
my $filter_modules = {
885+
bool => {
886+
should => [
887+
map +{ term => { 'dependency.module' => $_ } },
888+
@{$modules}
889+
]
890+
}
891+
};
892+
893+
my $depended = $self->es->search(
894+
index => $self->index->name,
895+
type => 'release',
896+
body => {
897+
query => {
898+
bool => {
899+
must => [
900+
$filter_modules,
901+
{ term => { status => 'latest' } },
902+
{ term => { authorized => 1 } },
903+
]
904+
}
905+
},
906+
size => $page_size,
907+
from => $page * $page_size - $page_size,
908+
sort => $sort,
909+
}
910+
);
911+
return unless $depended->{hits}{total};
912+
913+
return [ map { $_->{_source} } @{ $depended->{hits}{hits} } ];
914+
}
915+
798916
__PACKAGE__->meta->make_immutable;
799917
1;

lib/MetaCPAN/Server/Controller/Release.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ sub files : Path('files') : Args(1) {
6767
$c->stash($data);
6868
}
6969

70+
# TODO: remove after deployed in Controller::ReverseDependencies
7071
sub requires : Path('requires') : Args(1) {
7172
my ( $self, $c, $module ) = @_;
7273
my @params = @{ $c->req->params }{qw< page page_size sort >};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package MetaCPAN::Server::Controller::ReverseDependencies;
2+
3+
use strict;
4+
use warnings;
5+
6+
use Moose;
7+
8+
BEGIN { extends 'MetaCPAN::Server::Controller' }
9+
10+
__PACKAGE__->config( namespace => 'reverse_dependencies' );
11+
12+
with 'MetaCPAN::Server::Role::JSONP';
13+
14+
sub dist : Path('dist') : Args(1) {
15+
my ( $self, $c, $dist ) = @_;
16+
my $data = $c->model('CPAN::Release')->reverse_dependencies($dist);
17+
$c->detach('/not_found') unless $data;
18+
$c->stash($data);
19+
}
20+
21+
sub module : Path('module') : Args(1) {
22+
my ( $self, $c, $module ) = @_;
23+
my @params = @{ $c->req->params }{qw< page page_size sort >};
24+
my $data = $c->model('CPAN::Release')->raw->requires( $module, @params );
25+
$c->detach('/not_found') unless $data;
26+
$c->stash($data);
27+
}
28+
29+
1;

0 commit comments

Comments
 (0)