MT#57223 improve sems audio cache invalidation

* clear_audio_cache is now invoked also from:
  - when a sound file is added (to reflect use_parent/potential child
    sets)
  - when a parent is changed for a sound set (to reflect current
    and potential child sets)
  - when a sound set is removed (to reflect potential child sets)
* clear_audio_cache() is reworked
  - clear_audio_cache() now calls virtual_child_sound_sets to
    fetch all potentially affected child sound sets and also
    clears audio cache for them. if the amount of fetched
    sound_sets is greater than 10000 then the the whole audio
    cache is invalidated
* _clear_audio_cache_service() is reworked
  - supports/expects a list of sound sets and sends them
    as a string with ':' separator
  - if both sound handle and sound sets are provided it calls
    clearFiles (so that only the specific sound handle is cleared)
  - if only sound sets are provided it calls clearSets (so that
    all of the cached files beloning to the sets are removed)
  - if none of the above are provided it calls clearAll to invalidate
    the whole cache

Change-Id: Ie85f208e27183e88665803b93bb16d7de8e3d7ac
mr11.4
Kirill Solomko 3 years ago
parent b566c28b3e
commit 89173442f3

@ -3,6 +3,7 @@ use NGCP::Panel::Utils::Generic qw(:all);
use Sipwise::Base; use Sipwise::Base;
use HTTP::Status qw(:constants); use HTTP::Status qw(:constants);
use NGCP::Panel::Utils::Sems;
use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::SoundSets/; use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::SoundSets/;
@ -85,6 +86,10 @@ sub delete_item {
})->delete_all; # explicit delete_all, otherwise query fails })->delete_all; # explicit delete_all, otherwise query fails
} }
# clear audio cache of the current sound set and
# and all potentially affected children sets
NGCP::Panel::Utils::Sems::clear_audio_cache($c, $item->id);
$item->delete; $item->delete;
return 1; return 1;

@ -235,6 +235,7 @@ sub edit :Chained('base') :PathPart('edit') {
my $parent_loop_err; my $parent_loop_err;
try { try {
my $own_id = $c->stash->{set_result}->id; my $own_id = $c->stash->{set_result}->id;
my $old_parent_id = $c->stash->{set_result}->parent_id;
my $parent_id = $form->values->{parent_id} = $form->values->{parent}{id} // undef; my $parent_id = $form->values->{parent_id} = $form->values->{parent}{id} // undef;
if ($c->user->roles eq "admin") { if ($c->user->roles eq "admin") {
$form->values->{reseller_id} = $form->values->{reseller}{id}; $form->values->{reseller_id} = $form->values->{reseller}{id};
@ -293,6 +294,14 @@ sub edit :Chained('base') :PathPart('edit') {
NGCP::Panel::Utils::Sounds::contract_sound_set_propagate( NGCP::Panel::Utils::Sounds::contract_sound_set_propagate(
$c, $c->stash->{set_result}->contract, $c->stash->{set_result}->id); $c, $c->stash->{set_result}->contract, $c->stash->{set_result}->id);
} }
# invalidate cache of this sound set if parent is changed
if ((!$old_parent_id && $parent_id) ||
($old_parent_id && !$parent_id) ||
$old_parent_id != $parent_id) {
NGCP::Panel::Utils::Sems::clear_audio_cache($c, $own_id);
}
}); });
delete $c->session->{created_objects}->{reseller}; delete $c->session->{created_objects}->{reseller};
delete $c->session->{created_objects}->{contract}; delete $c->session->{created_objects}->{contract};
@ -329,6 +338,7 @@ sub delete_sound :Chained('base') :PathPart('delete') {
my $schema = $c->model('DB'); my $schema = $c->model('DB');
$schema->txn_do(sub { $schema->txn_do(sub {
my $own_id = $c->stash->{set_result}->id;
# remove all usr_preferenes where this set is assigned # remove all usr_preferenes where this set is assigned
if($c->stash->{set_result}->contract_id) { if($c->stash->{set_result}->contract_id) {
my $pref_rs = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( my $pref_rs = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
@ -345,6 +355,10 @@ sub delete_sound :Chained('base') :PathPart('delete') {
})->delete_all; # explicit delete_all, otherwise query fails })->delete_all; # explicit delete_all, otherwise query fails
} }
# clear audio cache of the current sound set and
# all potentially affected children sets
NGCP::Panel::Utils::Sems::clear_audio_cache($c, $own_id);
$c->stash->{set_result}->delete; $c->stash->{set_result}->delete;
}); });
NGCP::Panel::Utils::Message::info( NGCP::Panel::Utils::Message::info(
@ -592,19 +606,6 @@ sub handles_edit :Chained('handles_base') :PathPart('edit') {
my $target_codec = 'WAV'; my $target_codec = 'WAV';
# clear audio caches
my $group_name = $file_result->handle->group->name;
try {
NGCP::Panel::Utils::Sems::clear_audio_cache($c, $file_result->set_id, $file_result->handle->name, $group_name);
} catch ($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => "Failed to clear audio cache for " . $group_name . " at appserver",
desc => $c->loc('Failed to clear audio cache.'),
);
NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri});
}
try { try {
$soundfile = NGCP::Panel::Utils::Sounds::transcode_file( $soundfile = NGCP::Panel::Utils::Sounds::transcode_file(
$upload->tempname, 'WAV', $target_codec); $upload->tempname, 'WAV', $target_codec);
@ -654,6 +655,20 @@ sub handles_edit :Chained('handles_base') :PathPart('edit') {
); );
} }
} }
# clear audio caches
my $group_name = $file_result->handle->group->name;
try {
NGCP::Panel::Utils::Sems::clear_audio_cache($c, $file_result->set_id, $file_result->handle->name, $group_name);
} catch ($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => "Failed to clear audio cache for " . $group_name . " at appserver",
desc => $c->loc('Failed to clear audio cache.'),
);
NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri});
}
NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri});
} }

@ -10,6 +10,7 @@ use Data::HAL qw();
use Data::HAL::Link qw(); use Data::HAL::Link qw();
use HTTP::Status qw(:constants); use HTTP::Status qw(:constants);
use NGCP::Panel::Utils::Sounds; use NGCP::Panel::Utils::Sounds;
use NGCP::Panel::Utils::Sems;
sub resource_name{ sub resource_name{
return 'soundsets'; return 'soundsets';
@ -182,6 +183,15 @@ sub update_item_model {
NGCP::Panel::Utils::Sounds::revoke_exposed_sound_set($c, $item->id); NGCP::Panel::Utils::Sounds::revoke_exposed_sound_set($c, $item->id);
} }
# invalidate cache of this sound set if parent is changed
my $old_parent_id = $old_resource->{parent_id};
my $parent_id = $resource->{parent_id};
if ((!$old_parent_id && $parent_id) ||
($old_parent_id && !$parent_id) ||
$old_parent_id != $parent_id) {
NGCP::Panel::Utils::Sems::clear_audio_cache($c, $item->id);
}
return $item; return $item;
} }

@ -359,26 +359,31 @@ EOF
sub clear_audio_cache { sub clear_audio_cache {
my ($c, $sound_set_id, $handle_name, $group_name) = @_; my ($c, $sound_set_id, $handle_name, $group_name) = @_;
my @pbx = $c->config->{features}->{cloudpbx} ? ('pbx') : (); my $rs = $c->model('DB')->resultset('virtual_child_sound_sets')->search({
my @services; },{
if ($group_name eq "pbx" ) { bind => [$sound_set_id],
@services = (@pbx); });
} elsif ($group_name =~ /^(music_on_hold|digits|custom_announcements)$/) {
@services = (@pbx, "appserver"); my $count = $rs->count;
} elsif ($group_name =~ /^(malicious_call_identification|voucher_recharge|play_balance|conference|calling_card)$/) {
@services = ("appserver");
}
for my $service (@services) { if ($count > 10000) { # invalidate the whole sems audio cache if the amount of child sound sets is too big
_clear_audio_cache_service($c, $service, $sound_set_id, $handle_name); _clear_audio_cache_service($c, "appserver", undef, undef);
} else {
my @sound_sets = map { $_->id } $rs->all;
_clear_audio_cache_service($c, "appserver", \@sound_sets, $handle_name)
} }
return; return;
} }
sub _clear_audio_cache_service { sub _clear_audio_cache_service {
my ($c, $service, $sound_set_id, $handle_name) = @_; my ($c, $service, $sound_sets, $handle_name) = @_;
my @ret = NGCP::Panel::Utils::XMLDispatcher::dispatch($c, $service, 1, 1, <<EOF ); my $msg;
my $sound_sets_str = $sound_sets ? join(':', @{$sound_sets}) : undef;
if ($handle_name && $sound_sets_str) {
$msg = <<EOF
<?xml version="1.0"?> <?xml version="1.0"?>
<methodCall> <methodCall>
<methodName>postDSMEvent</methodName> <methodName>postDSMEvent</methodName>
@ -390,22 +395,68 @@ sub _clear_audio_cache_service {
<value><array><data> <value><array><data>
<value><array><data> <value><array><data>
<value><string>cmd</string></value> <value><string>cmd</string></value>
<value><string>clearFile</string></value> <value><string>clearFiles</string></value>
</data></array></value> </data></array></value>
<value><array><data> <value><array><data>
<value><string>audio_id</string></value> <value><string>handle_name</string></value>
<value><string>$handle_name</string></value> <value><string>$handle_name</string></value>
</data></array></value> </data></array></value>
<value><array><data> <value><array><data>
<value><string>sound_set_id</string></value> <value><string>sound_sets</string></value>
<value><string>$sound_set_id</string></value> <value><string>$sound_sets_str</string></value>
</data></array></value> </data></array></value>
</data></array></value> </data></array></value>
</param> </param>
</params> </params>
</methodCall>
EOF
} elsif ($sound_sets_str) {
$msg = <<EOF
<?xml version="1.0"?>
<methodCall>
<methodName>postDSMEvent</methodName>
<params>
<param>
<value><string>sw_audio</string></value>
</param>
<param>
<value><array><data>
<value><array><data>
<value><string>cmd</string></value>
<value><string>clearSets</string></value>
</data></array></value>
<value><array><data>
<value><string>sound_sets</string></value>
<value><string>$sound_sets_str</string></value>
</data></array></value>
</data></array></value>
</param>
</params>
</methodCall>
EOF
} else {
$msg = <<EOF
<?xml version="1.0"?>
<methodCall>
<methodName>postDSMEvent</methodName>
<params>
<param>
<value><string>sw_audio</string></value>
</param>
<param>
<value><array><data>
<value><array><data>
<value><string>cmd</string></value>
<value><string>clearAll</string></value>
</data></array></value>
</data></array></value>
</param>
</params>
</methodCall> </methodCall>
EOF EOF
}
my @ret = NGCP::Panel::Utils::XMLDispatcher::dispatch($c, $service, 1, 1, $msg);
if (grep { $$_[1] == 0 || ($$_[1] != -1 && $$_[2] !~ m#<value>OK</value>#) } @ret) { # error if (grep { $$_[1] == 0 || ($$_[1] != -1 && $$_[2] !~ m#<value>OK</value>#) } @ret) { # error
die "failed to clear SEMS audio cache"; die "failed to clear SEMS audio cache";
} }

Loading…
Cancel
Save