MT#14255 panel UI problem setting subscriber 'lock' detail

Change-Id: I4873b36526152da64334a8359ce8bfe531ce42a6
changes/93/2693/1
Rene Krenn 10 years ago
parent f3cfa0ec87
commit 7dfc5fda21

@ -187,6 +187,30 @@ class_has 'query_params' => (
}, },
}, },
}, },
{
param => 'reseller_id',
description => 'Filter for subscribers of customers belonging to a specific reseller',
query => {
first => sub {
my $q = shift;
{ 'contract.contact.reseller_id' => $q };
},
second => sub {
{ join => 'contract.contact' };
},
},
},
{
param => 'contact_id',
description => 'Filter for subscribers of contracts with a specific contact id',
query => {
first => sub {
my $q = shift;
{ 'contract.contact_id' => $q };
},
second => sub {},
},
},
]}, ]},
); );
@ -222,12 +246,24 @@ sub GET :Allow {
my ($self, $c) = @_; my ($self, $c) = @_;
my $page = $c->request->params->{page} // 1; my $page = $c->request->params->{page} // 1;
my $rows = $c->request->params->{rows} // 10; my $rows = $c->request->params->{rows} // 10;
my $schema = $c->model('DB');
$schema->set_transaction_isolation('READ COMMITTED');
my $guard = $schema->txn_scope_guard;
{ {
my $subscribers = $self->item_rs($c); my $subscribers_rs = $self->item_rs($c);
(my $total_count, $subscribers) = $self->paginate_order_collection($c, $subscribers); (my $total_count, $subscribers_rs) = $self->paginate_order_collection($c, $subscribers_rs);
my (@embedded, @links); my $subscribers = NGCP::Panel::Utils::ProfilePackages::lock_contracts(c => $c,
rs => $subscribers_rs,
contract_id_field => 'contract_id');
my $now = NGCP::Panel::Utils::DateTime::current_local;
my (@embedded, @links, %contract_map);
my $form = $self->get_form($c); my $form = $self->get_form($c);
for my $subscriber ($subscribers->all) { for my $subscriber (@$subscribers) {
my $contract = $subscriber->contract;
my $balance = NGCP::Panel::Utils::ProfilePackages::get_contract_balance(c => $c,
contract => $contract,
now => $now) if !exists $contract_map{$contract->id}; #apply underrun lock level
$contract_map{$contract->id} = 1;
my $resource = $self->resource_from_item($c, $subscriber, $form); my $resource = $self->resource_from_item($c, $subscriber, $form);
push @embedded, $self->hal_from_item($c, $subscriber, $resource, $form); push @embedded, $self->hal_from_item($c, $subscriber, $resource, $form);
push @links, Data::HAL::Link->new( push @links, Data::HAL::Link->new(
@ -235,6 +271,7 @@ sub GET :Allow {
href => sprintf('%s%d', $self->dispatch_path, $subscriber->id), href => sprintf('%s%d', $self->dispatch_path, $subscriber->id),
); );
} }
$self->delay_commit($c,$guard);
push @links, push @links,
Data::HAL::Link->new( Data::HAL::Link->new(
relation => 'curies', relation => 'curies',

@ -9,6 +9,7 @@ use HTTP::Status qw(:constants);
use MooseX::ClassAttribute qw(class_has); use MooseX::ClassAttribute qw(class_has);
use NGCP::Panel::Utils::ValidateJSON qw(); use NGCP::Panel::Utils::ValidateJSON qw();
use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::DateTime;
use NGCP::Panel::Utils::ProfilePackages qw();
use Path::Tiny qw(path); use Path::Tiny qw(path);
use Safe::Isa qw($_isa); use Safe::Isa qw($_isa);
BEGIN { extends 'Catalyst::Controller::ActionRole'; } BEGIN { extends 'Catalyst::Controller::ActionRole'; }
@ -52,14 +53,22 @@ sub auto :Private {
sub GET :Allow { sub GET :Allow {
my ($self, $c, $id) = @_; my ($self, $c, $id) = @_;
$c->model('DB')->set_transaction_isolation('READ COMMITTED');
my $guard = $c->model('DB')->txn_scope_guard;
{ {
last unless $self->valid_id($c, $id); last unless $self->valid_id($c, $id);
my $subscriber = $self->item_by_id($c, $id); my $subscriber = $self->item_by_id($c, $id);
last unless $self->resource_exists($c, subscriber => $subscriber); last unless $self->resource_exists($c, subscriber => $subscriber);
my $balance = NGCP::Panel::Utils::ProfilePackages::get_contract_balance(c => $c,
contract => $subscriber->contract,
); #apply underrun lock level
my $form = $self->get_form($c); my $form = $self->get_form($c);
my $resource = $self->resource_from_item($c, $subscriber, $form); my $resource = $self->resource_from_item($c, $subscriber, $form);
my $hal = $self->hal_from_item($c, $subscriber, $resource, $form); my $hal = $self->hal_from_item($c, $subscriber, $resource, $form);
$guard->commit; #potential db write ops in hal_from
my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new( my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new(
(map { # XXX Data::HAL must be able to generate links with multiple relations (map { # XXX Data::HAL must be able to generate links with multiple relations
@ -97,6 +106,7 @@ sub OPTIONS :Allow {
sub PUT :Allow { sub PUT :Allow {
my ($self, $c, $id) = @_; my ($self, $c, $id) = @_;
my $schema = $c->model('DB'); my $schema = $c->model('DB');
$schema->set_transaction_isolation('READ COMMITTED');
my $guard = $schema->txn_scope_guard; my $guard = $schema->txn_scope_guard;
{ {
my $preference = $self->require_preference($c); my $preference = $self->require_preference($c);
@ -104,6 +114,9 @@ sub PUT :Allow {
my $subscriber = $self->item_by_id($c, $id); my $subscriber = $self->item_by_id($c, $id);
last unless $self->resource_exists($c, subscriber => $subscriber); last unless $self->resource_exists($c, subscriber => $subscriber);
my $balance = NGCP::Panel::Utils::ProfilePackages::get_contract_balance(c => $c,
contract => $subscriber->contract,
); #apply underrun lock level
my $resource = $self->get_valid_put_data( my $resource = $self->get_valid_put_data(
c => $c, c => $c,
id => $id, id => $id,
@ -112,6 +125,7 @@ sub PUT :Allow {
last unless $resource; last unless $resource;
my $r = $self->prepare_resource($c, $schema, $resource, $subscriber); my $r = $self->prepare_resource($c, $schema, $resource, $subscriber);
last unless $r; last unless $r;
$resource = $r->{resource}; $resource = $r->{resource};
my $form = $self->get_form($c); my $form = $self->get_form($c);
@ -145,6 +159,7 @@ sub PUT :Allow {
sub PATCH :Allow { sub PATCH :Allow {
my ($self, $c, $id) = @_; my ($self, $c, $id) = @_;
my $schema = $c->model('DB'); my $schema = $c->model('DB');
$schema->set_transaction_isolation('READ COMMITTED');
my $guard = $schema->txn_scope_guard; my $guard = $schema->txn_scope_guard;
{ {
my $preference = $self->require_preference($c); my $preference = $self->require_preference($c);
@ -152,6 +167,9 @@ sub PATCH :Allow {
my $subscriber = $self->item_by_id($c, $id); my $subscriber = $self->item_by_id($c, $id);
last unless $self->resource_exists($c, subscriber => $subscriber); last unless $self->resource_exists($c, subscriber => $subscriber);
my $balance = NGCP::Panel::Utils::ProfilePackages::get_contract_balance(c => $c,
contract => $subscriber->contract,
); #apply underrun lock level
my $json = $self->get_valid_patch_data( my $json = $self->get_valid_patch_data(
c => $c, c => $c,
id => $id, id => $id,

@ -1997,16 +1997,13 @@ sub preferences_callforward_delete :Chained('base') :PathPart('preferences/callf
$c->uri_for_action('/subscriber/preferences', [$c->req->captures->[0]])); $c->uri_for_action('/subscriber/preferences', [$c->req->captures->[0]]));
} }
sub load_preference_list :Private { sub underrun_catchup :Private {
my ($self, $c) = @_; my ($self, $c) = @_;
my $reseller_id = $c->stash->{subscriber}->contract->contact->reseller_id;
try { try {
my $schema = $c->model('DB'); my $schema = $c->model('DB');
$schema->set_transaction_isolation('READ COMMITTED'); $schema->set_transaction_isolation('READ COMMITTED');
$schema->txn_do(sub { $schema->txn_do(sub {
NGCP::Panel::Utils::ProfilePackages::underrun_lock_subscriber(c => $c, subscriber => $c->stash->{subscriber}); NGCP::Panel::Utils::ProfilePackages::get_contract_balance(c => $c, contract => $c->stash->{subscriber}->contract);
}); });
} catch($e) { } catch($e) {
NGCP::Panel::Utils::Message->error( NGCP::Panel::Utils::Message->error(
@ -2016,8 +2013,16 @@ sub load_preference_list :Private {
desc => $c->loc('Failed to check and apply underrun subscriber lock level'), desc => $c->loc('Failed to check and apply underrun subscriber lock level'),
); );
$c->response->redirect($c->uri_for()); $c->response->redirect($c->uri_for());
return; #return;
} }
}
sub load_preference_list :Private {
my ($self, $c) = @_;
my $reseller_id = $c->stash->{subscriber}->contract->contact->reseller_id;
$self->underrun_catchup($c);
my $usr_pref_values = $c->model('DB') my $usr_pref_values = $c->model('DB')
->resultset('voip_preferences') ->resultset('voip_preferences')
@ -2117,6 +2122,8 @@ sub master :Chained('base') :PathPart('details') :CaptureArgs(0) {
template => 'subscriber/master.tt', template => 'subscriber/master.tt',
); );
$self->underrun_catchup($c);
$c->stash->{prov_lock} = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( $c->stash->{prov_lock} = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, c => $c,
attribute => 'lock', attribute => 'lock',
@ -2127,6 +2134,8 @@ sub master :Chained('base') :PathPart('details') :CaptureArgs(0) {
sub details :Chained('master') :PathPart('') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) :AllowedRole('subscriberadmin') { sub details :Chained('master') :PathPart('') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) :AllowedRole('subscriberadmin') {
my ($self, $c) = @_; my ($self, $c) = @_;
$self->underrun_catchup($c);
$c->stash->{prov_lock} = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( $c->stash->{prov_lock} = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, c => $c,
attribute => 'lock', attribute => 'lock',
@ -2284,6 +2293,7 @@ sub edit_master :Chained('master') :PathPart('edit') :Args(0) :Does(ACL) :ACLDet
} }
my $schema = $c->model('DB'); my $schema = $c->model('DB');
try { try {
$schema->set_transaction_isolation('READ COMMITTED');
$schema->txn_do(sub { $schema->txn_do(sub {
my $email = delete $form->params->{email}; my $email = delete $form->params->{email};
@ -2561,15 +2571,22 @@ sub edit_master :Chained('master') :PathPart('edit') :Args(0) :Does(ACL) :ACLDet
} }
$form->values->{lock} ||= 0; $form->values->{lock} ||= 0;
if($lock->first) { NGCP::Panel::Utils::ProfilePackages::get_contract_balance(c => $c, contract => $subscriber->contract);
if ($form->values->{lock} == 0) { NGCP::Panel::Utils::Subscriber::lock_provisoning_voip_subscriber(
$lock->delete; c => $c,
} else { prov_subscriber => $subscriber->provisioning_voip_subscriber,
$lock->first->update({ value => $form->values->{lock} }); level => $form->values->{lock},
} ) if ($subscriber->provisioning_voip_subscriber);
} elsif($form->values->{lock} > 0) {
$lock->create({ value => $form->values->{lock} }); #if($lock->first) {
} # if ($form->values->{lock} == 0) {
# $lock->delete;
# } else {
# $lock->first->update({ value => $form->values->{lock} });
# }
#} elsif($form->values->{lock} > 0) {
# $lock->create({ value => $form->values->{lock} });
#}
}); });
delete $c->session->{created_objects}->{group}; delete $c->session->{created_objects}->{group};
NGCP::Panel::Utils::Message->info( NGCP::Panel::Utils::Message->info(

@ -437,7 +437,7 @@ sub apply_patch {
$entity = $coderef->('JSON::Pointer', $entity, $op->{path}, $op->{value}); $entity = $coderef->('JSON::Pointer', $entity, $op->{path}, $op->{value});
} }
} else { } else {
$pe->rethrow; die($pe); #->rethrow;
} }
} }
} elsif ('remove' eq $_) { } elsif ('remove' eq $_) {
@ -450,7 +450,7 @@ sub apply_patch {
$entity = $coderef->('JSON::Pointer', $entity, $op->{path}); $entity = $coderef->('JSON::Pointer', $entity, $op->{path});
} }
} else { } else {
$pe->rethrow; die($pe); #->rethrow;
} }
} }
} elsif ('move' eq $_ or 'copy' eq $_) { } elsif ('move' eq $_ or 'copy' eq $_) {
@ -463,7 +463,7 @@ sub apply_patch {
$entity = $coderef->('JSON::Pointer', $entity, $op->{from}, $op->{path}); $entity = $coderef->('JSON::Pointer', $entity, $op->{from}, $op->{path});
} }
} else { } else {
$pe->rethrow; die($pe); #->rethrow;
} }
} }
} elsif ('test' eq $_) { } elsif ('test' eq $_) {
@ -478,7 +478,7 @@ sub apply_patch {
unless $coderef->('JSON::Pointer', $entity, $op->{path}, $op->{value}); unless $coderef->('JSON::Pointer', $entity, $op->{path}, $op->{value});
} }
} else { } else {
$pe->rethrow; die($pe); #->rethrow;
} }
} }
} }

@ -102,6 +102,7 @@ sub hal_from_contract {
Data::HAL::Link->new(relation => 'ngcp:systemcontacts', href => sprintf("/api/systemcontacts/%d", $contract->contact->id)), Data::HAL::Link->new(relation => 'ngcp:systemcontacts', href => sprintf("/api/systemcontacts/%d", $contract->contact->id)),
@profile_links, @profile_links,
@network_links, @network_links,
Data::HAL::Link->new(relation => 'ngcp:balanceintervals', href => sprintf("/api/balanceintervals/%d", $contract->id)),
$self->get_journal_relation_link($contract->id), $self->get_journal_relation_link($contract->id),
], ],
relation => 'ngcp:'.$self->resource_name, relation => 'ngcp:'.$self->resource_name,

@ -100,6 +100,7 @@ sub hal_from_customer {
@network_links, @network_links,
$customer->profile_package_id ? Data::HAL::Link->new(relation => 'ngcp:profilepackages', href => sprintf("/api/profilepackages/%d", $customer->profile_package_id)) : (), $customer->profile_package_id ? Data::HAL::Link->new(relation => 'ngcp:profilepackages', href => sprintf("/api/profilepackages/%d", $customer->profile_package_id)) : (),
Data::HAL::Link->new(relation => 'ngcp:customerbalances', href => sprintf("/api/customerbalances/%d", $customer->id)), Data::HAL::Link->new(relation => 'ngcp:customerbalances', href => sprintf("/api/customerbalances/%d", $customer->id)),
Data::HAL::Link->new(relation => 'ngcp:balanceintervals', href => sprintf("/api/balanceintervals/%d", $customer->id)),
$customer->invoice_template ? (Data::HAL::Link->new(relation => 'ngcp:invoicetemplates', href => sprintf("/api/invoicetemplates/%d", $customer->invoice_template_id))) : (), $customer->invoice_template ? (Data::HAL::Link->new(relation => 'ngcp:invoicetemplates', href => sprintf("/api/invoicetemplates/%d", $customer->invoice_template_id))) : (),
$customer->subscriber_email_template_id ? (Data::HAL::Link->new(relation => 'ngcp:subscriberemailtemplates', href => sprintf("/api/emailtemplates/%d", $customer->subscriber_email_template_id))) : (), $customer->subscriber_email_template_id ? (Data::HAL::Link->new(relation => 'ngcp:subscriberemailtemplates', href => sprintf("/api/emailtemplates/%d", $customer->subscriber_email_template_id))) : (),
$customer->passreset_email_template_id ? (Data::HAL::Link->new(relation => 'ngcp:passresetemailtemplates', href => sprintf("/api/emailtemplates/%d", $customer->passreset_email_template_id))) : (), $customer->passreset_email_template_id ? (Data::HAL::Link->new(relation => 'ngcp:passresetemailtemplates', href => sprintf("/api/emailtemplates/%d", $customer->passreset_email_template_id))) : (),

@ -152,6 +152,10 @@ sub item_rs {
$item_rs = $c->model('DB')->resultset('voip_subscribers') $item_rs = $c->model('DB')->resultset('voip_subscribers')
->search({ 'me.status' => { '!=' => 'terminated' } }); ->search({ 'me.status' => { '!=' => 'terminated' } });
if($c->user->roles eq "admin") { if($c->user->roles eq "admin") {
$item_rs = $item_rs->search(undef,
{
join => { 'contract' => 'contact' }, #for filters
});
} elsif($c->user->roles eq "reseller") { } elsif($c->user->roles eq "reseller") {
$item_rs = $item_rs->search({ $item_rs = $item_rs->search({
'contact.reseller_id' => $c->user->reseller_id, 'contact.reseller_id' => $c->user->reseller_id,

@ -188,6 +188,21 @@ $res = $ua->request($req);
is($res->code, 200, "fetch customer contact 5"); is($res->code, 200, "fetch customer contact 5");
my $custcontact5 = JSON::from_json($res->decoded_content); my $custcontact5 = JSON::from_json($res->decoded_content);
$req = HTTP::Request->new('POST', $uri.'/api/customercontacts/');
$req->header('Content-Type' => 'application/json');
$req->content(JSON::to_json({
firstname => "cust_contact_9_first",
lastname => "cust_contact_9_last",
email => "cust_contact9\@custcontact.invalid",
reseller_id => $default_reseller_id,
}));
$res = $ua->request($req);
is($res->code, 201, "create customer contact 9");
$req = HTTP::Request->new('GET', $uri.'/'.$res->header('Location'));
$res = $ua->request($req);
is($res->code, 200, "fetch customer contact 9");
my $custcontact9 = JSON::from_json($res->decoded_content);
$req = HTTP::Request->new('POST', $uri.'/api/domains/'); $req = HTTP::Request->new('POST', $uri.'/api/domains/');
$req->header('Content-Type' => 'application/json'); $req->header('Content-Type' => 'application/json');
$req->content(JSON::to_json({ $req->content(JSON::to_json({
@ -874,7 +889,7 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) {
if (_get_allow_delay_commit()) { if (_get_allow_delay_commit()) {
_set_time(NGCP::Panel::Utils::DateTime::current_local->subtract(months => 3)); _set_time(NGCP::Panel::Utils::DateTime::current_local->subtract(months => 3));
_create_customers_threaded(3,undef,undef,$custcontact5); _create_customers_threaded(3,undef,undef,$custcontact9);
_create_customers_threaded(3,undef,undef,$custcontact2); _create_customers_threaded(3,undef,undef,$custcontact2);
_set_time(); _set_time();
@ -883,7 +898,7 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) {
my $t_a = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact2); my $t_a = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact2);
my $t_b = threads->create(\&_fetch_customerbalances_worker,$delay,'id','desc',$custcontact2); my $t_b = threads->create(\&_fetch_customerbalances_worker,$delay,'id','desc',$custcontact2);
my $t_c = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact5); my $t_c = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact9);
my $intervals_a = $t_a->join(); my $intervals_a = $t_a->join();
my $intervals_b = $t_b->join(); my $intervals_b = $t_b->join();
my $intervals_c = $t_c->join(); my $intervals_c = $t_c->join();
@ -891,7 +906,7 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) {
#my $got_a = [ sort { $a->{id} <=> $b->{id} } @{ $intervals_b->{_embedded}->{'ngcp:balanceintervals'} } ]; #$a->{contract_id} #my $got_a = [ sort { $a->{id} <=> $b->{id} } @{ $intervals_b->{_embedded}->{'ngcp:balanceintervals'} } ]; #$a->{contract_id}
is($intervals_a->{total_count},3,"check total count of thread a results"); is($intervals_a->{total_count},3,"check total count of thread a results");
is($intervals_b->{total_count},3,"check total count of thread b results"); is($intervals_b->{total_count},3,"check total count of thread b results");
is($intervals_c->{total_count},scalar (grep { $_->{contact_id} == $custcontact5->{id} } values %customer_map),"check total count of thread c results"); is($intervals_c->{total_count},scalar (grep { $_->{contact_id} == $custcontact9->{id} } values %customer_map),"check total count of thread c results");
my $got_asc = $intervals_a->{_embedded}->{'ngcp:customerbalances'}; my $got_asc = $intervals_a->{_embedded}->{'ngcp:customerbalances'};
my $got_desc = $intervals_b->{_embedded}->{'ngcp:customerbalances'}; my $got_desc = $intervals_b->{_embedded}->{'ngcp:customerbalances'};
if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare customerbalances collection results of threaded requests deeply')) { if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare customerbalances collection results of threaded requests deeply')) {
@ -921,7 +936,7 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) {
if (_get_allow_delay_commit()) { if (_get_allow_delay_commit()) {
_set_time(NGCP::Panel::Utils::DateTime::current_local->subtract(months => 3)); _set_time(NGCP::Panel::Utils::DateTime::current_local->subtract(months => 3));
_create_customers_threaded(3,undef,undef,$custcontact5); _create_customers_threaded(3,undef,undef,$custcontact9);
_create_customers_threaded(3,undef,undef,$custcontact3); _create_customers_threaded(3,undef,undef,$custcontact3);
_set_time(); _set_time();
@ -930,14 +945,14 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) {
my $t_a = threads->create(\&_fetch_intervals_worker,$delay,'id','asc',$custcontact3); my $t_a = threads->create(\&_fetch_intervals_worker,$delay,'id','asc',$custcontact3);
my $t_b = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact3); my $t_b = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact3);
my $t_c = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact5); my $t_c = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact9);
my $intervals_a = $t_a->join(); my $intervals_a = $t_a->join();
my $intervals_b = $t_b->join(); my $intervals_b = $t_b->join();
my $intervals_c = $t_c->join(); my $intervals_c = $t_c->join();
my $t2 = time; my $t2 = time;
is($intervals_a->{total_count},3,"check total count of thread a results"); is($intervals_a->{total_count},3,"check total count of thread a results");
is($intervals_b->{total_count},3,"check total count of thread b results"); is($intervals_b->{total_count},3,"check total count of thread b results");
is($intervals_c->{total_count},scalar (grep { $_->{contact_id} == $custcontact5->{id} } values %customer_map),"check total count of thread c results"); is($intervals_c->{total_count},scalar (grep { $_->{contact_id} == $custcontact9->{id} } values %customer_map),"check total count of thread c results");
#my $got_a = [ sort { $a->{id} <=> $b->{id} } @{ $intervals_b->{_embedded}->{'ngcp:balanceintervals'} } ]; #$a->{contract_id} #my $got_a = [ sort { $a->{id} <=> $b->{id} } @{ $intervals_b->{_embedded}->{'ngcp:balanceintervals'} } ]; #$a->{contract_id}
my $got_asc = $intervals_a->{_embedded}->{'ngcp:balanceintervals'}; my $got_asc = $intervals_a->{_embedded}->{'ngcp:balanceintervals'};
my $got_desc = $intervals_b->{_embedded}->{'ngcp:balanceintervals'}; my $got_desc = $intervals_b->{_embedded}->{'ngcp:balanceintervals'};
@ -970,21 +985,21 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) {
if (_get_allow_delay_commit()) { if (_get_allow_delay_commit()) {
my $package = _create_profile_package('create','month',1,initial_balance => 1, carry_over_mode => 'discard', underrun_lock_threshold => 1, underrun_lock_level => 4); my $package = _create_profile_package('create','month',1,initial_balance => 1, carry_over_mode => 'discard', underrun_lock_threshold => 1, underrun_lock_level => 4);
_set_time(NGCP::Panel::Utils::DateTime::from_string('2015-05-17 13:00:00')); _set_time(NGCP::Panel::Utils::DateTime::from_string('2015-05-17 13:00:00'));
_create_customers_threaded(3,2,$package,$custcontact5); _create_customers_threaded(3,2,$package,$custcontact9);
_create_customers_threaded(3,2,$package,$custcontact4); _create_customers_threaded(3,2,$package,$custcontact4);
my $t1 = time; my $t1 = time;
my $delay = 10.0; #15.0; #10.0; #2.0; my $delay = 15.0; #15.0; #10.0; #2.0;
my $t_a = threads->create(\&_fetch_preferences_worker,$delay,'id','asc',$custcontact4); my $t_a = threads->create(\&_fetch_preferences_worker,$delay,'id','asc',$custcontact4);
my $t_b = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact4); my $t_b = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact4);
my $t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact5); my $t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact9);
my $prefs_a = $t_a->join(); my $prefs_a = $t_a->join();
my $prefs_b = $t_b->join(); my $prefs_b = $t_b->join();
my $prefs_c = $t_c->join(); my $prefs_c = $t_c->join();
my $t2 = time; my $t2 = time;
is($prefs_a->{total_count},2*3,"check total count of thread a results"); is($prefs_a->{total_count},2*3,"check total count of thread a results");
is($prefs_b->{total_count},2*3,"check total count of thread b results"); is($prefs_b->{total_count},2*3,"check total count of thread b results");
is($prefs_c->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact5->{id} } values %subscriber_map),"check total count of thread c results"); is($prefs_c->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{id} } values %subscriber_map),"check total count of thread c results");
my $got_asc = $prefs_a->{_embedded}->{'ngcp:subscriberpreferences'}; my $got_asc = $prefs_a->{_embedded}->{'ngcp:subscriberpreferences'};
my $got_desc = $prefs_b->{_embedded}->{'ngcp:subscriberpreferences'}; my $got_desc = $prefs_b->{_embedded}->{'ngcp:subscriberpreferences'};
if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare subscriber preference collection results of threaded requests deeply')) { if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare subscriber preference collection results of threaded requests deeply')) {
@ -1002,14 +1017,14 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) {
$t_a = threads->create(\&_fetch_preferences_worker,$delay,'id','asc',$custcontact4); $t_a = threads->create(\&_fetch_preferences_worker,$delay,'id','asc',$custcontact4);
$t_b = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact4); $t_b = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact4);
$t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact5); $t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact9);
$prefs_a = $t_a->join(); $prefs_a = $t_a->join();
$prefs_b = $t_b->join(); $prefs_b = $t_b->join();
$prefs_c = $t_c->join(); $prefs_c = $t_c->join();
$t2 = time; $t2 = time;
is($prefs_a->{total_count},2*3,"check total count of thread a results"); is($prefs_a->{total_count},2*3,"check total count of thread a results");
is($prefs_b->{total_count},2*3,"check total count of thread b results"); is($prefs_b->{total_count},2*3,"check total count of thread b results");
is($prefs_c->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact5->{id} } values %subscriber_map),"check total count of thread c results"); is($prefs_c->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{id} } values %subscriber_map),"check total count of thread c results");
$got_asc = $prefs_a->{_embedded}->{'ngcp:subscriberpreferences'}; $got_asc = $prefs_a->{_embedded}->{'ngcp:subscriberpreferences'};
$got_desc = $prefs_b->{_embedded}->{'ngcp:subscriberpreferences'}; $got_desc = $prefs_b->{_embedded}->{'ngcp:subscriberpreferences'};
if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare subscriber preference collection results of threaded requests deeply')) { if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare subscriber preference collection results of threaded requests deeply')) {
@ -1053,12 +1068,99 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) {
} else { } else {
diag('allow_delay_commit not set, skipping ...'); diag('allow_delay_commit not set, skipping ...');
} }
if (_get_allow_delay_commit()) {
my $package = _create_profile_package('create','month',1,initial_balance => 1, carry_over_mode => 'discard', underrun_lock_threshold => 1, underrun_lock_level => 4);
_set_time(NGCP::Panel::Utils::DateTime::from_string('2015-05-17 13:00:00'));
_create_customers_threaded(3,2,$package,$custcontact9);
_create_customers_threaded(3,2,$package,$custcontact5);
my $t1 = time;
my $delay = 15.0; #15.0; #10.0; #2.0;
my $t_a = threads->create(\&_fetch_subscribers_worker,$delay,'id','asc',$custcontact5);
my $t_b = threads->create(\&_fetch_subscribers_worker,$delay,'id','desc',$custcontact5);
my $t_c = threads->create(\&_fetch_subscribers_worker,$delay,'id','desc',$custcontact9);
my $subs_a = $t_a->join();
my $subs_b = $t_b->join();
my $subs_c = $t_c->join();
my $t2 = time;
is($subs_a->{total_count},2*3,"check total count of thread a results");
is($subs_b->{total_count},2*3,"check total count of thread b results");
is($subs_c->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{id} } values %subscriber_map),"check total count of thread c results");
my $got_asc = $subs_a->{_embedded}->{'ngcp:subscribers'};
my $got_desc = $subs_b->{_embedded}->{'ngcp:subscribers'};
if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare subscriber collection results of threaded requests deeply')) {
diag(Dumper({asc => $got_asc, desc => $got_desc}));
}
ok($t2 - $t1 > 2*$delay,'expected delay to assume subscribers requests were processed after another');
ok($t2 - $t1 < 3*$delay,'expected delay to assume only required contracts were locked');
for (my $i = 0; $i < 2*3; $i++) {
is($got_desc->[$i]->{lock},undef,"check if subscriber is unlocked initially");
}
_set_time(NGCP::Panel::Utils::DateTime::from_string('2015-06-18 13:00:00'));
$t1 = time;
$t_a = threads->create(\&_fetch_subscribers_worker,$delay,'id','asc',$custcontact5);
$t_b = threads->create(\&_fetch_subscribers_worker,$delay,'id','desc',$custcontact5);
$t_c = threads->create(\&_fetch_subscribers_worker,$delay,'id','desc',$custcontact9);
$subs_a = $t_a->join();
$subs_b = $t_b->join();
$subs_c = $t_c->join();
$t2 = time;
is($subs_a->{total_count},2*3,"check total count of thread a results");
is($subs_b->{total_count},2*3,"check total count of thread b results");
is($subs_c->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{id} } values %subscriber_map),"check total count of thread c results");
$got_asc = $subs_a->{_embedded}->{'ngcp:subscribers'};
$got_desc = $subs_b->{_embedded}->{'ngcp:subscribers'};
if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare subscriber collection results of threaded requests deeply')) {
diag(Dumper({asc => $got_asc, desc => $got_desc}));
}
ok($t2 - $t1 > 2*$delay,'expected delay to assume subscribers requests were processed after another');
ok($t2 - $t1 < 3*$delay,'expected delay to assume only required contracts were locked');
for (my $i = 0; $i < 2*3; $i++) {
is($got_desc->[$i]->{lock},4,"check if subscriber is locked now");
}
$t1 = time;
$t_a = threads->create(\&_fetch_subscribers_worker,$delay,'id','asc',$custcontact5);
$t_b = threads->create(\&_fetch_subscribers_worker,$delay,'id','desc',$custcontact5);
$t_c = threads->create(\&_fetch_subscribers_worker,$delay,'id','desc',$custcontact5);
$subs_a = $t_a->join();
$subs_b = $t_b->join();
$subs_c = $t_c->join();
$t2 = time;
is($subs_a->{total_count},2*3,"check total count of thread a results");
is($subs_b->{total_count},2*3,"check total count of thread b results");
is($subs_c->{total_count},2*3,"check total count of thread c results");
ok($t2 - $t1 > 3*$delay,'expected delay to assume subscribers requests were processed after another');
$t1 = time;
$t_a = threads->create(\&_fetch_subscribers_worker,$delay,'id','asc',$custcontact5);
sleep($delay/2.0);
my $last_customer_id = shift(@{[sort {$b <=> $a} keys %customer_map]});
_check_interval_history($customer_map{$last_customer_id},[
{ start => '2015-05-17 00:00:00', stop => '2015-06-16 23:59:59', cash => 0.01, package_id => $package->{id}, profile => $billingprofile->{id} },
{ start => '2015-06-17 00:00:00', stop => '2015-07-16 23:59:59', cash => 0, package_id => $package->{id}, profile => $billingprofile->{id} },
]);
$t2 = time;
$t_a->join();
ok($t2 - $t1 > $delay,'expected delay to assume subscribers request locks contracts and an simultaneous access to contract id ' . $last_customer_id . ' is serialized');
_set_time();
} else {
diag('allow_delay_commit not set, skipping ...');
}
} else { } else {
diag('allow_fake_client_time not set, skipping ...'); diag('allow_fake_client_time not set, skipping ...');
} }
for my $custcontact ($custcontact1,$custcontact2,$custcontact3,$custcontact4,$custcontact5) { for my $custcontact ($custcontact1,$custcontact2,$custcontact3,$custcontact4,$custcontact9) {
{ #test balanceintervals root collection and item { #test balanceintervals root collection and item
_create_customers_threaded(3,undef,undef,$custcontact); # unless _get_allow_fake_client_time() && $enable_profile_packages; _create_customers_threaded(3,undef,undef,$custcontact); # unless _get_allow_fake_client_time() && $enable_profile_packages;
@ -1692,6 +1794,8 @@ sub _create_subscriber {
is($res->code, 201, "POST test subscriber"); is($res->code, 201, "POST test subscriber");
my $request = $req; my $request = $req;
$req = HTTP::Request->new('GET', $uri.'/'.$res->header('Location')); $req = HTTP::Request->new('GET', $uri.'/'.$res->header('Location'));
$req->header('X-Fake-Clienttime' => _get_fake_clienttime_now());
$req->header('X-Request-Identifier' => $req_identifier) if $req_identifier;
$res = $ua->request($req); $res = $ua->request($req);
is($res->code, 200, "fetch POSTed test subscriber"); is($res->code, 200, "fetch POSTed test subscriber");
my $subscriber = JSON::from_json($res->decoded_content); my $subscriber = JSON::from_json($res->decoded_content);
@ -1799,6 +1903,21 @@ sub _fetch_preferences_worker {
return $result; return $result;
} }
sub _fetch_subscribers_worker {
my ($delay,$sort_column,$dir,$custcontact) = @_;
diag("starting thread " . threads->tid() . " ...");
$req = HTTP::Request->new('GET', $uri.'/api/subscribers/?order_by='.$sort_column.'&order_by_direction='.$dir.'&contact_id='.$custcontact->{id}.'&rows='.(scalar keys %subscriber_map));
$req->header('X-Fake-Clienttime' => _get_fake_clienttime_now());
$req->header('X-Request-Identifier' => $req_identifier) if $req_identifier;
$req->header('X-Delay-Commit' => $delay);
$res = $ua->request($req);
is($res->code, 200, "thread " . threads->tid() . ": concurrent fetch subscribers of contracts of contact id ".$custcontact->{id} . " in " . $dir . " order");
my $result = JSON::from_json($res->decoded_content);
#is($result->{total_count},(scalar keys %subscriber_map),"check total count");
diag("finishing thread " . threads->tid() . " ...");
return $result;
}
sub _record_request { sub _record_request {
my ($label,$request,$req_data,$res_data) = @_; my ($label,$request,$req_data,$res_data) = @_;
if ($tb) { if ($tb) {

Loading…
Cancel
Save