TT#167400 change call forwardings preference to be distinct

* Call forwardings related internal usr preferences are now
  distinct per call forward type (maximum 1 record per call
  forward type, if at least one forwarding for this type exists).
  This change is meant to address the issue when there are >1000
  call forwardings per subscriber, which leads to performance
  issues. Other components (kamailio) only uses this preference
  as a boolean to check if there are call forwardings at all per
  type, therefore, more than one preference, per type, per subscriber
  is not needed.

Change-Id: Iffa475700a74f56eff67400ce9b57092018a14a0
mr10.4
Kirill Solomko 3 years ago
parent 4df49f5639
commit 4554155627

@ -1098,10 +1098,13 @@ sub preferences_callforward :Chained('base') :PathPart('preferences/callforward'
else { else {
$map->update({enabled => $cf_form->field('enabled')->value}); $map->update({enabled => $cf_form->field('enabled')->value});
} }
foreach my $pref($cf_preference->all) {
$pref->delete; if ($cf_preference->first) {
} $cf_preference->first->update({ value => $map->id });
} else {
$cf_preference->create({ value => $map->id }); $cf_preference->create({ value => $map->id });
}
if($cf_type eq 'cft') { if($cf_type eq 'cft') {
if($ringtimeout_preference->first) { if($ringtimeout_preference->first) {
if (!$cf_form->field('enabled')->value) { if (!$cf_form->field('enabled')->value) {
@ -1280,8 +1283,8 @@ sub preferences_callforward_advanced :Chained('base') :PathPart('preferences/cal
$autoattendant_count += NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($map->destination_set); $autoattendant_count += NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($map->destination_set);
$map->delete; $map->delete;
} }
$cf_preference->delete_all;
unless(@active) { unless(@active) {
$cf_preference->delete_all;
$ringtimeout_preference->first->delete $ringtimeout_preference->first->delete
if($cf_type eq "cft" && $ringtimeout_preference->first); if($cf_type eq "cft" && $ringtimeout_preference->first);
NGCP::Panel::Utils::Message::info( NGCP::Panel::Utils::Message::info(
@ -1296,6 +1299,7 @@ sub preferences_callforward_advanced :Chained('base') :PathPart('preferences/cal
return; return;
} }
} }
my $cf_pref_created = 0;
foreach my $map(@active) { foreach my $map(@active) {
my $m = $cf_mapping->create({ my $m = $cf_mapping->create({
type => $cf_type, type => $cf_type,
@ -1305,7 +1309,15 @@ sub preferences_callforward_advanced :Chained('base') :PathPart('preferences/cal
bnumber_set_id => $map->field('bnumber_set')->value, bnumber_set_id => $map->field('bnumber_set')->value,
enabled => $map->field('enabled')->value, enabled => $map->field('enabled')->value,
}); });
if (!$cf_pref_created) {
if ($cf_preference->count != 1) {
$cf_preference->delete_all;
$cf_preference->create({ value => $m->id }); $cf_preference->create({ value => $m->id });
} else {
$cf_preference->first->update({ value => $m->id });
}
$cf_pref_created = 1;
}
$autoattendant_count -= NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($m->destination_set); $autoattendant_count -= NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($m->destination_set);
} }
if ($autoattendant_count > 0) { if ($autoattendant_count > 0) {
@ -1491,13 +1503,14 @@ sub preferences_callforward_destinationset_edit :Chained('preferences_callforwar
[$c->req->captures->[0]], $cf_type); [$c->req->captures->[0]], $cf_type);
my $posted = ($c->request->method eq 'POST'); my $posted = ($c->request->method eq 'POST');
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => $cf_type, attribute => $cf_type,
); );
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => 'ringtimeout', attribute => 'ringtimeout',
); );
@ -1546,8 +1559,6 @@ sub preferences_callforward_destinationset_edit :Chained('preferences_callforwar
my @fields = $form->field('destination')->fields; my @fields = $form->field('destination')->fields;
unless(@fields) { unless(@fields) {
foreach my $mapping($set->voip_cf_mappings->all) { foreach my $mapping($set->voip_cf_mappings->all) {
my $cf = $cf_preference->find({ value => $mapping->id });
$cf->delete if $cf;
$ringtimeout_preference->first->delete $ringtimeout_preference->first->delete
if($cf_type eq "cft" && $ringtimeout_preference->first); if($cf_type eq "cft" && $ringtimeout_preference->first);
$mapping->delete; $mapping->delete;
@ -1559,6 +1570,11 @@ sub preferences_callforward_destinationset_edit :Chained('preferences_callforwar
); );
} }
$set->delete; $set->delete;
my $maps = $prov_subscriber->voip_cf_mappings->search;
if (!$maps->first) {
$cf_preference->delete_all;
}
NGCP::Panel::Utils::Navigation::back_or($c, $fallback, 1); NGCP::Panel::Utils::Navigation::back_or($c, $fallback, 1);
return; return;
} }
@ -1621,24 +1637,22 @@ sub preferences_callforward_destinationset_edit :Chained('preferences_callforwar
sub preferences_callforward_destinationset_delete :Chained('preferences_callforward_destinationset_base') :PathPart('delete') :Args(1) { sub preferences_callforward_destinationset_delete :Chained('preferences_callforward_destinationset_base') :PathPart('delete') :Args(1) {
my ($self, $c, $cf_type) = @_; my ($self, $c, $cf_type) = @_;
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => $cf_type, attribute => $cf_type,
); );
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => 'ringtimeout', attribute => 'ringtimeout',
); );
my $set = $c->stash->{destination_set}; my $set = $c->stash->{destination_set};
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
try { try {
my $schema = $c->model('DB'); my $schema = $c->model('DB');
$schema->txn_do(sub { $schema->txn_do(sub {
my $autoattendant = NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($set); my $autoattendant = NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($set);
foreach my $map($set->voip_cf_mappings->all) { foreach my $map($set->voip_cf_mappings->all) {
my $cf = $cf_preference->find({ value => $map->id });
$cf->delete if $cf;
$map->delete; $map->delete;
if ($autoattendant) { if ($autoattendant) {
NGCP::Panel::Utils::Events::insert( NGCP::Panel::Utils::Events::insert(
@ -1653,6 +1667,10 @@ sub preferences_callforward_destinationset_delete :Chained('preferences_callforw
$ringtimeout_preference->first->delete; $ringtimeout_preference->first->delete;
} }
$set->delete; $set->delete;
my $maps = $prov_subscriber->voip_cf_mappings->search;
if (!$maps->first) {
$cf_preference->delete_all;
}
}); });
NGCP::Panel::Utils::Message::info( NGCP::Panel::Utils::Message::info(
c => $c, c => $c,
@ -1800,9 +1818,10 @@ sub preferences_callforward_sourceset_edit :Chained('preferences_callforward_sou
[$c->req->captures->[0]], $cf_type); [$c->req->captures->[0]], $cf_type);
my $posted = ($c->request->method eq 'POST'); my $posted = ($c->request->method eq 'POST');
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => $cf_type, attribute => $cf_type,
); );
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
@ -1847,13 +1866,15 @@ sub preferences_callforward_sourceset_edit :Chained('preferences_callforward_sou
my @fields = $form->field('source')->fields; my @fields = $form->field('source')->fields;
unless(@fields) { unless(@fields) {
foreach my $mapping($set->voip_cf_mappings->all) { foreach my $mapping($set->voip_cf_mappings->all) {
my $cf = $cf_preference->find({ value => $mapping->id });
$cf->delete if $cf;
$ringtimeout_preference->first->delete $ringtimeout_preference->first->delete
if($cf_type eq "cft" && $ringtimeout_preference->first); if($cf_type eq "cft" && $ringtimeout_preference->first);
$mapping->delete; $mapping->delete;
} }
$set->delete; $set->delete;
my $maps = $prov_subscriber->voip_cf_mappings->search;
if (!$maps->first) {
$cf_preference->delete_all;
}
NGCP::Panel::Utils::Navigation::back_or($c, $fallback, 1); NGCP::Panel::Utils::Navigation::back_or($c, $fallback, 1);
return; return;
} }
@ -1904,30 +1925,30 @@ sub preferences_callforward_sourceset_edit :Chained('preferences_callforward_sou
sub preferences_callforward_sourceset_delete :Chained('preferences_callforward_sourceset_base') :PathPart('delete') :Args(1) { sub preferences_callforward_sourceset_delete :Chained('preferences_callforward_sourceset_base') :PathPart('delete') :Args(1) {
my ($self, $c, $cf_type) = @_; my ($self, $c, $cf_type) = @_;
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => $cf_type, attribute => $cf_type,
); );
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => 'ringtimeout', attribute => 'ringtimeout',
); );
my $set = $c->stash->{source_set}; my $set = $c->stash->{source_set};
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
try { try {
my $schema = $c->model('DB'); my $schema = $c->model('DB');
$schema->txn_do(sub { $schema->txn_do(sub {
foreach my $map($set->voip_cf_mappings->all) { $set->voip_cf_mappings->delete_all;
my $cf = $cf_preference->find({ value => $map->id });
$cf->delete if $cf;
$map->delete;
}
if($cf_type eq "cft" && if($cf_type eq "cft" &&
$prov_subscriber->voip_cf_mappings->search_rs({ type => $cf_type})->count == 0) { $prov_subscriber->voip_cf_mappings->search_rs({ type => $cf_type})->count == 0) {
$ringtimeout_preference->first->delete; $ringtimeout_preference->first->delete;
} }
$set->delete; $set->delete;
my $maps = $prov_subscriber->voip_cf_mappings->search;
if (!$maps->first) {
$cf_preference->delete_all;
}
}); });
NGCP::Panel::Utils::Message::info( NGCP::Panel::Utils::Message::info(
c => $c, c => $c,
@ -2075,13 +2096,14 @@ sub preferences_callforward_bnumberset_edit :Chained('preferences_callforward_bn
[$c->req->captures->[0]], $cf_type); [$c->req->captures->[0]], $cf_type);
my $posted = ($c->request->method eq 'POST'); my $posted = ($c->request->method eq 'POST');
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => $cf_type, attribute => $cf_type,
); );
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => 'ringtimeout', attribute => 'ringtimeout',
); );
@ -2122,14 +2144,15 @@ sub preferences_callforward_bnumberset_edit :Chained('preferences_callforward_bn
my @fields = $form->field('bnumbers')->fields; my @fields = $form->field('bnumbers')->fields;
unless(@fields) { unless(@fields) {
foreach my $mapping($set->voip_cf_mappings->all) { foreach my $mapping($set->voip_cf_mappings->all) {
# delete it here (this has been a design decicion from the beginning for all parts of cfs)
my $cf = $cf_preference->find({ value => $mapping->id });
$cf->delete if $cf;
$ringtimeout_preference->first->delete $ringtimeout_preference->first->delete
if($cf_type eq "cft" && $ringtimeout_preference->first); if($cf_type eq "cft" && $ringtimeout_preference->first);
$mapping->delete; $mapping->delete;
} }
$set->delete; $set->delete;
my $maps = $prov_subscriber->voip_cf_mappings->search;
if (!$maps->first) {
$cf_preference->delete_all;
}
NGCP::Panel::Utils::Navigation::back_or($c, $fallback, 1); NGCP::Panel::Utils::Navigation::back_or($c, $fallback, 1);
return; return;
} }
@ -2180,30 +2203,31 @@ sub preferences_callforward_bnumberset_edit :Chained('preferences_callforward_bn
sub preferences_callforward_bnumberset_delete :Chained('preferences_callforward_bnumberset_base') :PathPart('delete') :Args(1) { sub preferences_callforward_bnumberset_delete :Chained('preferences_callforward_bnumberset_base') :PathPart('delete') :Args(1) {
my ($self, $c, $cf_type) = @_; my ($self, $c, $cf_type) = @_;
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => $cf_type, attribute => $cf_type,
); );
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber, c => $c, prov_subscriber => $prov_subscriber,
attribute => 'ringtimeout', attribute => 'ringtimeout',
); );
my $set = $c->stash->{bnumber_set}; my $set = $c->stash->{bnumber_set};
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
try { try {
my $schema = $c->model('DB'); my $schema = $c->model('DB');
$schema->txn_do(sub { $schema->txn_do(sub {
foreach my $map($set->voip_cf_mappings->all) { $set->voip_cf_mappings->delete_all;
my $cf = $cf_preference->find({ value => $map->id });
$cf->delete if $cf;
$map->delete;
}
if($cf_type eq "cft" && if($cf_type eq "cft" &&
$prov_subscriber->voip_cf_mappings->search_rs({ type => $cf_type})->count == 0) { $prov_subscriber->voip_cf_mappings->search_rs({ type => $cf_type})->count == 0) {
$ringtimeout_preference->first->delete; $ringtimeout_preference->first->delete;
} }
$set->delete; $set->delete;
my $maps = $prov_subscriber->voip_cf_mappings->search;
if (!$maps->first) {
$cf_preference->delete_all;
}
}); });
NGCP::Panel::Utils::Message::info( NGCP::Panel::Utils::Message::info(
c => $c, c => $c,

@ -346,13 +346,11 @@ sub update_cf_mappings {
$autoattendant_count += NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($map->destination_set); $autoattendant_count += NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($map->destination_set);
} }
$mappings_rs->delete; $mappings_rs->delete;
for my $type ( qw/cfu cfb cft cfna cfs cfr cfo/) {
$cf_preferences{$type}->delete;
}
} }
$mappings_rs->populate(\@new_mappings); $mappings_rs->populate(\@new_mappings);
for my $type ( qw/cfu cfb cft cfna cfs cfr cfo/) { for my $type ( qw/cfu cfb cft cfna cfs cfr cfo/) {
my $cf_preference = $cf_preferences{$type};
my @mapping_ids_by_type = $mappings_rs->search( my @mapping_ids_by_type = $mappings_rs->search(
{ {
type => $type type => $type
@ -363,7 +361,14 @@ sub update_cf_mappings {
result_class => 'DBIx::Class::ResultClass::HashRefInflator' result_class => 'DBIx::Class::ResultClass::HashRefInflator'
} }
)->all(); )->all();
$cf_preferences{$type}->populate(\@mapping_ids_by_type); if (!@mapping_ids_by_type) {
$cf_preference->delete;
} elsif ($cf_preference->count != 1) {
$cf_preference->delete;
$cf_preference->create($mapping_ids_by_type[0]);
} else {
$cf_preference->update($mapping_ids_by_type[0]);
}
} }
unless ($params->{add_only}) { unless ($params->{add_only}) {

Loading…
Cancel
Save