MT#60162 improve expand functionality for collections

* in general expand collection now performs only 1 sql
  query to per expand field to fetch all items by the ids
  instead of fetching them for every single collection item,
  that should significantly increase performance in case
  of large databases and reduce work for the database
* introduce $c->stash->{expand_cache} that contains
  cached data for the expand fields to avoid multiple
  same calculations
* expand_field() and expand_field_data() have been reworked
  to support expand_cache
* new method expand_prepare_collection() is called for all
  API GET collection methods before preparing resource hal
  fields, to change the expand logic to only cache the data
  instead of fetching it from the database
* new method expand_collection_fields() that is called in all
  API GET collection methods after the @embedded data is prepared
  to finalise the expand collection fields
* for expand collection there is only 1 SQL request per expand field
  that fetches all items -in [ids to expand] and then the
  expand_collection_fields() uses the cached items_by_ids with
  O(1) fetch from the cache by id

Change-Id: Ie7c6115472878febf0d8c9b4d833f5c23b15c78b
(cherry picked from commit 6543743992)
mr10.5
Kirill Solomko 11 months ago
parent b527ea73a7
commit 2c58f1867d

@ -52,6 +52,7 @@ sub GET :Allow {
my $subscribers = $self->item_rs($c);
(my $total_count, $subscribers, my $subscribers_rows) = $self->paginate_order_collection($c, $subscribers);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $subscriber (@$subscribers_rows) {
push @embedded, $self->hal_from_item($c, $subscriber);
push @links, Data::HAL::Link->new(
@ -59,6 +60,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $subscriber->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -99,6 +99,7 @@ sub GET :Allow {
contract_id_field => 'id');
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $contract (@$contracts) {
my $balance = NGCP::Panel::Utils::ProfilePackages::get_contract_balance(c => $c,
contract => $contract,
@ -112,6 +113,7 @@ sub GET :Allow {
push @links, $link;
#push @links, Data::HAL::Link->new(relation => 'collection', href => sprintf("/api/%s/%d/", $self->resource_name, $contract->id));
}
$self->expand_collection_fields($c, \@embedded);
$self->delay_commit($c,$guard);
push @links,
Data::HAL::Link->new(

@ -82,6 +82,7 @@ sub GET :Allow {
(my $total_count, $fees, my $fees_rows) = $self->paginate_order_collection($c, $fees);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $fee (@$fees_rows) {
push @embedded, $self->hal_from_fee($c, $fee, $form);
push @links, Data::HAL::Link->new(
@ -89,6 +90,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $fee->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -81,6 +81,7 @@ sub GET :Allow {
(my $total_count, $bns, my $bns_rows) = $self->paginate_order_collection($c, $bns);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $bn (@$bns_rows) {
push @embedded, $self->hal_from_item($c, $bn, "billingnetworks");
push @links, Data::HAL::Link->new(
@ -88,6 +89,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $bn->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -73,6 +73,7 @@ sub GET :Allow {
(my $total_count, $profiles, my $profiles_rows) = $self->paginate_order_collection($c, $profiles);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $profile (@$profiles_rows) {
push @embedded, $self->hal_from_item($c, $profile, $self->resource_from_item($c, $profile, $form), $form);
push @links, Data::HAL::Link->new(
@ -80,6 +81,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $profile->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -66,6 +66,7 @@ sub GET :Allow {
(my $total_count, $zones, my $zones_rows) = $self->paginate_order_collection($c, $zones);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $zone (@$zones_rows) {
push @embedded, $self->hal_from_zone($c, $zone, $form);
push @links, Data::HAL::Link->new(
@ -73,6 +74,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $zone->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -50,6 +50,7 @@ sub GET :Allow {
my $cfs = $self->item_rs($c);
(my $total_count, $cfs, my $cfs_rows) = $self->paginate_order_collection($c, $cfs);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $cf (@$cfs_rows) {
try {
push @embedded, $self->hal_from_item($c, $cf, "ccmapentries");
@ -59,6 +60,7 @@ sub GET :Allow {
);
}
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -70,6 +70,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $subs (@$items_rows) {
push @embedded, $self->hal_from_item($c, $subs, "cfmappings");
push @links, Data::HAL::Link->new(
@ -77,6 +78,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $subs->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -77,6 +77,7 @@ sub GET :Allow {
(my $total_count, $ssets, my $ssets_rows) = $self->paginate_order_collection($c, $ssets);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $sset (@$ssets_rows) {
push @embedded, $self->hal_from_item($c, $sset, "cfsourcesets");
push @links, Data::HAL::Link->new(
@ -84,6 +85,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $sset->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -321,6 +321,7 @@ sub GET :Allow {
my $href_data = $owner->{subscriber} ?
"subscriber_id=".$owner->{subscriber}->id :
"customer_id=".$owner->{customer}->id;
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form, { 'owner' => $owner });
push @links, Data::HAL::Link->new(
@ -328,6 +329,7 @@ sub GET :Allow {
href => sprintf('/%s%d?%s', $c->request->path, $item->id, $href_data),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -82,6 +82,7 @@ sub GET :Allow {
(my $total_count, $callrecordingstreams, my $callrecordingstreams_rows) = $self->paginate_order_collection($c, $callrecordingstreams);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $domain (@$callrecordingstreams_rows) {
push @embedded, $self->hal_from_item($c, $domain, $form);
push @links, Data::HAL::Link->new(
@ -89,6 +90,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $domain->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -86,6 +86,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -93,6 +94,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -57,6 +57,7 @@ sub GET :Allow {
(my $total_count, $capabilities, my $capabilities_rows) = $self->paginate_order_collection($c, $capabilities);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $cap (@{ $capabilities_rows }) {
push @embedded, $self->hal_from_item($c, $cap, $form);
push @links, Data::HAL::Link->new(
@ -64,6 +65,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $cap->{id}),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -99,6 +99,7 @@ sub GET :Allow {
contract_id_field => 'id');
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $contract (@$contracts) {
#NGCP::Panel::Utils::ProfilePackages::get_contract_balance
push @embedded, $self->hal_from_contract($c, $contract, $form, $now);
@ -107,6 +108,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $contract->id),
);
}
$self->expand_collection_fields($c, \@embedded);
$self->delay_commit($c,$guard); #potential db write ops in hal_from
push @links,
Data::HAL::Link->new(

@ -129,6 +129,7 @@ sub GET :Allow {
contract_id_field => 'id');
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items) {
my $balance = $self->item_by_id($c, $item->id,$now);
push @embedded, $self->hal_from_item($c, $balance, $form);
@ -137,6 +138,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
$self->delay_commit($c,$guard);
push @links,
Data::HAL::Link->new(

@ -69,6 +69,7 @@ sub GET :Allow {
(my $total_count, $contacts, my $contacts_rows) = $self->paginate_order_collection($c, $contacts);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $contact (@$contacts_rows) {
push @embedded, $self->hal_from_contact($c, $contact, $form);
push @links, Data::HAL::Link->new(
@ -76,6 +77,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $contact->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -88,6 +88,7 @@ sub GET :Allow {
(my $total_count, $customer_rs, my $customer_rows) = $self->paginate_order_collection($c, $customer_rs);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $customer (@$customer_rows) {
push @embedded, $self->hal_from_item($c, $customer, $form);
push @links, Data::HAL::Link->new(
@ -95,6 +96,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $customer->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -69,6 +69,7 @@ sub GET :Allow {
(my $total_count, $cls, my $cls_rows) = $self->paginate_order_collection($c, $cls);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $cl (@$cls_rows) {
push @embedded, $self->hal_from_item($c, $cl, $self->resource_name);
push @links, Data::HAL::Link->new(
@ -76,6 +77,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $cl->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -75,6 +75,7 @@ sub GET :Allow {
return unless $query_string;
my (@embedded, @links);
my $error_flag = 0;
$self->expand_prepare_collection($c);
for my $dev (@$field_devs_rows) {
my $hal = $self->hal_from_item($c, $dev);
$error_flag = 1 unless $hal;
@ -85,6 +86,7 @@ sub GET :Allow {
);
}
last if $error_flag;
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -158,6 +158,7 @@ sub GET :Allow {
contract_id_field => 'id');
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $customer (@$customers) {
push @embedded, $self->hal_from_customer($c, $customer, $form, $now);
push @links, Data::HAL::Link->new(
@ -165,6 +166,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $customer->id),
);
}
$self->expand_collection_fields($c, \@embedded);
$self->delay_commit($c,$guard); #potential db write ops in hal_from
push @links,
Data::HAL::Link->new(

@ -61,6 +61,7 @@ sub GET :Allow {
(my $total_count, $domains, my $domains_rows) = $self->paginate_order_collection($c, $domains);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $domain (@$domains_rows) {
push @embedded, $self->hal_from_item($c, $domain, $form);
push @links, Data::HAL::Link->new(
@ -68,6 +69,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $domain->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -66,6 +66,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -73,6 +74,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -67,6 +67,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -74,6 +75,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -107,6 +107,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -114,6 +115,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -102,6 +102,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
my $hal = $self->hal_from_item($c, $item, $form);
$hal->_forcearray(1);
@ -113,6 +114,7 @@ sub GET :Allow {
$link->_forcearray(1);
push @links, $link;
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -85,6 +85,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -92,6 +93,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -68,6 +68,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -75,6 +76,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -61,6 +61,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -68,6 +69,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -98,6 +98,7 @@ sub GET :Allow {
#$t2 = time; print("page: " . ($t2 - $t1) . "secs\n"); $t1 = time;
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -105,6 +106,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -82,6 +82,7 @@ sub GET :Allow {
my $cfs = $self->item_rs($c);
(my $total_count, $cfs, my $cfs_rows) = $self->paginate_order_collection($c, $cfs);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $cf (@$cfs_rows) {
try {
push @embedded, $self->hal_from_item($c, $cf);
@ -91,6 +92,7 @@ sub GET :Allow {
);
}
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -130,6 +130,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -137,6 +138,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -70,6 +70,7 @@ sub GET :Allow {
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $cf (@$cfs_rows) {
try {
push @embedded, $self->hal_from_item($c, $cf, $form);
@ -79,6 +80,7 @@ sub GET :Allow {
);
}
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -68,6 +68,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -75,6 +76,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -72,6 +72,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -79,6 +80,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -61,6 +61,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -68,6 +69,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -61,6 +61,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -68,6 +69,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -83,6 +83,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -90,6 +91,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -84,6 +84,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -91,6 +92,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -61,6 +61,7 @@ sub GET :Allow {
(my $total_count, $field_devs, my $field_devs_rows) = $self->paginate_order_collection($c, $field_devs);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $dev (@$field_devs_rows) {
push @embedded, $self->hal_from_item($c, $dev);
push @links, Data::HAL::Link->new(
@ -68,6 +69,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $dev->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -115,6 +115,7 @@ sub GET :Allow {
(my $total_count, $field_devs, my $field_devs_rows) = $self->paginate_order_collection($c, $field_devs);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $dev (@$field_devs_rows) {
push @embedded, $self->hal_from_item($c, $dev);
push @links, Data::HAL::Link->new(
@ -122,6 +123,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $dev->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -48,6 +48,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -55,6 +56,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -78,6 +78,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -85,6 +86,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -82,6 +82,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -89,6 +90,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -87,6 +87,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -94,6 +95,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -95,6 +95,7 @@ sub GET :Allow {
(my $total_count, $packages, my $packages_rows) = $self->paginate_order_collection($c, $packages);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $package (@$packages_rows) {
push @embedded, $self->hal_from_item($c, $package, "profilepackages", $form);
push @links, Data::HAL::Link->new(
@ -102,6 +103,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $package->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -78,6 +78,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -85,6 +86,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -68,6 +68,7 @@ sub GET :Allow {
(my $total_count, $resellers, my $resellers_rows) = $self->paginate_order_collection($c, $resellers);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $reseller (@$resellers_rows) {
push @embedded, $self->hal_from_reseller($c, $reseller, $form);
push @links, Data::HAL::Link->new(
@ -75,6 +76,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $reseller->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -72,6 +72,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -79,6 +80,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -66,6 +66,7 @@ sub GET :Allow {
my $subscribers = $self->item_rs($c);
(my $total_count, $subscribers, my $subscribers_rows) = $self->paginate_order_collection($c, $subscribers);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $subscriber (@$subscribers_rows) {
push @embedded, $self->hal_from_item($c, $subscriber);
push @links, Data::HAL::Link->new(
@ -73,6 +74,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $subscriber->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -67,6 +67,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -74,6 +75,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -97,6 +97,7 @@ sub GET :Allow {
contract_id_field => 'contract_id');
my $now = NGCP::Panel::Utils::DateTime::current_local;
my (@embedded, @links, %contract_map);
$self->expand_prepare_collection($c);
for my $subscriber (@$subscribers) {
next unless($subscriber->provisioning_voip_subscriber);
my $contract = $subscriber->contract;
@ -110,6 +111,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $subscriber->id),
);
}
$self->expand_collection_fields($c, \@embedded);
$self->delay_commit($c,$guard);
push @links,
Data::HAL::Link->new(

@ -68,6 +68,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -75,6 +76,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -69,6 +69,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -76,6 +77,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -94,6 +94,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
my $halitem = $self->hal_from_item($c, $item, $form);
next unless($halitem);
@ -103,6 +104,7 @@ sub GET :Allow {
href => sprintf('/%s%s', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -322,6 +322,7 @@ sub GET :Allow {
my $now = NGCP::Panel::Utils::DateTime::current_local;
my (@embedded, @links, %contract_map);
my ($form) = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $subscriber (@$subscribers) {
my $contract = $subscriber->contract;
NGCP::Panel::Utils::ProfilePackages::get_contract_balance(c => $c,
@ -335,6 +336,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $subscriber->id),
);
}
$self->expand_collection_fields($c, \@embedded);
$self->delay_commit($c,$guard);
push @links,
Data::HAL::Link->new(

@ -58,6 +58,7 @@ sub GET :Allow {
(my $total_count, $contacts, my $contacts_rows) = $self->paginate_order_collection($c, $contacts);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $contact (@$contacts_rows) {
push @embedded, $self->hal_from_contact($c, $contact, $form);
push @links, Data::HAL::Link->new(
@ -65,6 +66,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $contact->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -167,6 +167,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
my $hal = $self->hal_from_item($c, $item, $form);
$hal->_forcearray(1);
@ -178,6 +179,7 @@ sub GET :Allow {
$link->_forcearray(1);
push @links, $link;
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -66,6 +66,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -73,6 +74,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -65,6 +65,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -72,6 +73,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -65,6 +65,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -72,6 +73,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->provisioning_voip_subscriber->voip_subscriber->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -82,6 +82,7 @@ sub GET :Allow {
my $items = $self->get_list($c);
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item);
push @links, Data::HAL::Link->new(
@ -89,6 +90,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -74,6 +74,7 @@ sub GET :Allow {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my $form = $self->get_form($c);
$self->expand_prepare_collection($c);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form);
push @links, Data::HAL::Link->new(
@ -81,6 +82,7 @@ sub GET :Allow {
href => sprintf('/%s%d', $c->request->path, $item->id),
);
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

@ -1318,6 +1318,48 @@ sub hal_from_item {
return $hal;
}
sub expand_prepare_collection {
my ($self, $c) = @_;
$c->stash->{expand_is_collection} = 1;
}
sub expand_collection_fields {
my ($self, $c, $embedded) = @_;
my $expand_cache = $c->stash->{expand_cache} // return;
my ($key_fields, $new_key_fields) = (0,0);
my $failsafe = 0;
my $max_failsafe = 100; # support max of 100 expand_field iterations
do {
$failsafe++;
$key_fields = keys %{$expand_cache};
$self->expand_check_prepared_cache($c);
for my $hal (@{$embedded}) {
$self->expand_fields($c, $hal->{resource});
}
$new_key_fields = keys %{$expand_cache};
} until ($key_fields == $new_key_fields || $failsafe == $max_failsafe);
#require Data::Dumper;
#print Data::Dumper->new([$expand_cache])->Terse(1)->Maxdepth(3)->Dump;
}
sub expand_check_prepared_cache {
my ($self, $c) = @_;
my $expand_cache = $c->stash->{expand_cache} // return;
for my $key_field (keys %{$expand_cache}) {
my $cache = $expand_cache->{$key_field};
next if $cache->{invalid};
$cache->{expanded} = 1 if $cache->{prepared};
$cache->{prepared} //= 1;
}
}
sub expand_fields {
my ($self, $c, $resource) = @_;
@ -1346,55 +1388,103 @@ sub expand_fields {
}
sub expand_field {
my ($self, $c, $resource, $resource_form, $field) = @_;
my ($self, $c, $resource, $resource_form, $field, $depth) = @_;
my ($subfield, $found);
if ($field =~ /^([^\.]+)\.(.+)/) {
$field = $1;
$subfield = $2;
$depth //= 0;
my ($pri_field, $key_field, $found);
my @fields = split(/\./, $field);
if (exists $fields[$depth]) {
$pri_field = $fields[$depth];
}
my @parents = @fields;
my @sub_fields = splice(@parents, $depth);
shift @sub_fields; # remove current field
my $parent = join('.', @parents);
$key_field = $depth == 0 ? $pri_field : $parent . '.' . $pri_field;
return unless exists $resource->{$field};
return unless exists $resource->{$pri_field};
$found = 1;
my $expand_form = NGCP::Panel::Form::get("NGCP::Panel::Form::Expand", $c);
my $cache = $c->stash->{expand_cache}{$key_field} //= {};
my ($attr, $expand);
my $f_field = $resource_form->field($field);
return if $cache->{invalid};
my $expand_form = $cache->{expand_form} //=
NGCP::Panel::Form::get("NGCP::Panel::Form::Expand", $c);
my ($attr, $expand) = @{$cache}{qw(attr expand)};
if (!$attr || !$expand) {
if (my $f_field = $resource_form->field($pri_field)) {
$attr = $f_field->element_attr;
$expand = $attr->{expand};
}
if (!$expand) { # use default field expand if specified
if (my $f_field = $expand_form->field($pri_field)) {
$attr = $f_field->element_attr;
$expand = $attr->{expand};
}
}
if ($f_field) {
$attr = $f_field->element_attr;
$expand = $attr->{expand};
if ($attr && $expand) {
$cache->{attr} = $attr;
$cache->{expand} = $expand;
} else {
$cache->{invalid} = 1;
return;
}
}
unless ($expand) { # use default field expand if specified
$f_field = $expand_form->field($field) // return;
$attr = $f_field->element_attr // return;
$expand = $attr->{expand} // return;
my ($to, $class, $form) = @{$cache}{qw(to class form)};
if (!$to || !$class || !$form) {
try {
die unless $expand->{allowed_roles};
die unless any { $c->user->roles eq $_ } @{$expand->{allowed_roles}};
$to = $expand->{to} // $pri_field . '_expand';
$class = $expand->{class} // die;
$form = $class->get_form($c) // die;
$cache->{to} = $to;
$cache->{class} = $class;
$cache->{form} = $form;
} catch ($e) {
$cache->{invalid} = 1;
return;
}
}
return unless $expand->{allowed_roles};
return unless any { $c->user->roles eq $_ } @{$expand->{allowed_roles}};
$cache->{parent} = $parent;
my $id = $resource->{$field} // return $found; # null value but the field exists
my $to = $expand->{to} // $field . '_expand';
my $class = $expand->{class} // return;
my $form = $class->get_form($c) // return;
my $id;
if (exists $resource->{$pri_field}) {
$id = $resource->{$pri_field} // return $found;
} else {
return;
}
if (ref $id eq 'ARRAY') {
for (my $i=0; $i<=$#$id; $i++) {
my $a_id = $id->[$i];
$resource->{$to}[$i] =
$self->get_expanded_field_data($c, $expand, $resource, $field, $class, $form, $a_id);
if ($subfield) {
$found = $self->expand_field($c, $resource->{$to}[$i], $form, $subfield);
if ($c->stash->{expand_is_collection} && !$cache->{prepared}) {
$cache->{ids}{$a_id} = 1;
} else {
$resource->{$to}[$i] =
$self->get_expanded_field_data($c, $expand, $resource, $key_field, $a_id);
}
if (@sub_fields) {
$found = $self->expand_field($c, $resource->{$to}[$i], $form, $field, $depth+1);
}
}
} else {
$resource->{$to} ||=
$self->get_expanded_field_data($c, $expand, $resource, $field, $class, $form, $id);
if ($subfield) {
$found = $self->expand_field($c, $resource->{$to}, $form, $subfield);
if ($c->stash->{expand_is_collection} && !$cache->{prepared}) {
$cache->{ids}{$id} = 1;
} else {
$resource->{$to} ||=
$self->get_expanded_field_data($c, $expand, $resource, $key_field, $id);
}
if (@sub_fields) {
$found = $self->expand_field($c, $resource->{$to}, $form, $field, $depth+1);
}
}
@ -1402,9 +1492,30 @@ sub expand_field {
}
sub get_expanded_field_data {
my ($self, $c, $expand, $resource, $field, $class, $form, $id) = @_;
my ($self, $c, $expand, $resource, $key_field, $id) = @_;
my $cache = $c->stash->{expand_cache}{$key_field} // return;
my ($class, $form) = @{$cache}{qw(class form)};
my $item = $class->item_by_id($c, $id) // return;
my $item;
if ($c->stash->{expand_is_collection}) {
return if !$cache->{prepared} && $cache->{expanded};
if (!$cache->{items_by_id} && $cache->{ids}) {
my %items_by_id = map { $_->id => $_ }
$class->item_rs($c)->search({
'me.id' => { '-in' => [keys %{$cache->{ids}}] },
},{
'order_by' => { '-asc' => 'id' },
})->all();
$cache->{items_by_id} = \%items_by_id;
}
$item = $cache->{items_by_id}{$id} // return;
} else {
$item = $class->item_by_id($c, $id) // return;
}
my $item_res = $class->resource_from_item($c, $item, $form);
my $data = $class->post_process_hal_resource($c, $item, $item_res, $form);

@ -211,10 +211,12 @@ sub get {
(my $total_count, $items, my $items_rows) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
my ($form) = $self->get_form($c);
$self->expand_collection_fields($c, \@embedded);
for my $item (@$items_rows) {
push @embedded, $self->hal_from_item($c, $item, $form, {});
push @links, grep { $_->relation->_original eq 'ngcp:'.$self->resource_name } @{$embedded[-1]->links};
}
$self->expand_collection_fields($c, \@embedded);
push @links,
Data::HAL::Link->new(
relation => 'curies',

Loading…
Cancel
Save