From 8494b5a91f406439eb94ba26b5dba09afd1e8a9b Mon Sep 17 00:00:00 2001 From: Rene Krenn Date: Wed, 23 Sep 2015 08:59:23 +0200 Subject: [PATCH] MT#14255 consider balance discard with infinite-end intervals +refactoring recent failing api-balanceintervals.t test to need only two concurrent transactions (instead of three, see https://bugtracker.sipwise.com/view.php?id=15277 Change-Id: I4902e616c3adfae81676194fa5e2b99e4b516ed1 --- lib/NGCP/Panel/Utils/ProfilePackages.pm | 98 +++++++-- t/api-rest/api-balanceintervals.t | 274 ++++++++++++++++-------- 2 files changed, 261 insertions(+), 111 deletions(-) diff --git a/lib/NGCP/Panel/Utils/ProfilePackages.pm b/lib/NGCP/Panel/Utils/ProfilePackages.pm index e747525976..ae170d88e5 100644 --- a/lib/NGCP/Panel/Utils/ProfilePackages.pm +++ b/lib/NGCP/Panel/Utils/ProfilePackages.pm @@ -148,13 +148,11 @@ sub resize_actual_contract_balance { } #underruns due to increased thresholds: + my $update = {}; if (_ENABLE_UNDERRUN_LOCK && defined $underrun_lock_threshold && ($actual_balance->cash_balance + $topup_amount) < $underrun_lock_threshold) { if (defined $new_package->underrun_lock_level) { set_subscriber_lock_level(c => $c, contract => $contract, lock_level => $new_package->underrun_lock_level); - $actual_balance->update({ - underrun_lock => $now, - }); - $actual_balance->discard_changes(); + $update->{underrun_lock} = $now; } } if (_ENABLE_UNDERRUN_PROFILES && defined $underrun_profile_threshold && ($actual_balance->cash_balance + $topup_amount) < $underrun_profile_threshold) { @@ -166,12 +164,13 @@ sub resize_actual_contract_balance { stime => $now, profiles => 'underrun_profiles', now => $now) > 0) { - $actual_balance->update({ - underrun_profiles => $now, - }); - $actual_balance->discard_changes(); + $update->{underrun_profiles} = $now; } } + if ((scalar keys %$update) > 0) { + $actual_balance->update($update); + $actual_balance->discard_changes(); + } } else { die("Another action finished meanwhile, please try again."); @@ -221,11 +220,12 @@ sub catchup_contract_balances { while ($last_balance && !NGCP::Panel::Utils::DateTime::is_infinite_future($last_balance->end) && $last_balance->end < $now) { #comparison takes 100++ sec if loaded lastbalance contains +inf my $start_of_next_interval = $last_balance->end->clone->add(seconds => 1); - unless ($is_notopup_expiration_calculated) { + if ($has_package && !$is_notopup_expiration_calculated) { #we have two queries here, so do it only if really creating contract_balances $notopup_expiration = _get_notopup_expiration(contract => $contract, notopup_discard_intervals => $notopup_discard_intervals, - interval_unit => $interval_unit); + interval_unit => $interval_unit, + start_mode => $start_mode); $is_notopup_expiration_calculated = 1; } @@ -294,6 +294,51 @@ PREPARE_BALANCE_CATCHUP: }); $last_balance->discard_changes(); } + + # in case of "topup" or "topup_interval" start modes, the current interval end can be + # infinite and no new contract balances are created. for this infinite end interval, + # the interval start represents the time the last topup happened in case of "topup". + # in case of "topup_interval", the interval start represents the contract creation. + # the cash balance should be discarded when + # 1. the current/call time is later than than $notopup_discard_intervals periods + # after the interval start, or + # 2. we have the "carry_over_timely" mode, and the current/call time is beyond + # the timely end already + if ($has_package && $last_balance && NGCP::Panel::Utils::DateTime::is_infinite_future($last_balance->end)) { + $notopup_expiration = _get_notopup_expiration(contract => $contract, + notopup_discard_intervals => $notopup_discard_intervals, + interval_unit => $interval_unit, + last_balance => $last_balance, + start_mode => $start_mode); + my $timely_end = (_CARRY_OVER_TIMELY_MODE eq $carry_over_mode ? _add_interval($last_balance->start,$interval_unit,$interval_value,undef)->subtract(seconds => 1) : undef); + if ((defined $notopup_expiration && $now >= $notopup_expiration) + || (defined $timely_end && $now > $timely_end)) { + my $update = { + cash_balance => 0 + }; + if (_ENABLE_UNDERRUN_LOCK && !$suppress_underrun && !$underrun_lock_applied && defined $underrun_lock_threshold && $last_balance->cash_balance >= $underrun_lock_threshold && ($update->{cash_balance} + $topup_amount) < $underrun_lock_threshold) { + $underrun_lock_applied = 1; + if (defined $old_package->underrun_lock_level) { + set_subscriber_lock_level(c => $c, contract => $contract, lock_level => $old_package->underrun_lock_level); + $update->{underrun_lock} = $now; + } + } + if (_ENABLE_UNDERRUN_PROFILES && !$suppress_underrun && !$underrun_profiles_applied && defined $underrun_profile_threshold && ($profiles_added > 0 || $last_balance->cash_balance >= $underrun_profile_threshold) && ($update->{cash_balance} + $topup_amount) < $underrun_profile_threshold) { + $underrun_profiles_applied = 1; + if (add_profile_mappings(c=> $c, + contract => $contract, + package => $old_package, + #bm_actual => $bm_actual, + stime => $now, + profiles => 'underrun_profiles', + now => $now) > 0) { + $update->{underrun_profiles} = $now; + } + } + $last_balance->update($update); + $last_balance->discard_changes(); + } + } return $last_balance; @@ -351,7 +396,7 @@ sub topup_contract_balance { $timely_end = $balance->end; } else { $timely_end = _add_interval($balance->start,$old_package->balance_interval_unit,$old_package->balance_interval_value, - _START_MODE_PRESERVE_EOM->{$old_package->balance_interval_start_mode} ? $contract->create_timestamp : undef)->subtract(seconds => 1); + _START_MODE_PRESERVE_EOM->{$old_package->balance_interval_start_mode} ? $contract->create_timestamp // $contract->modify_timestamp : undef)->subtract(seconds => 1); } my $timely_start = _add_interval($timely_end,$timely_duration_unit,-1 * $timely_duration_value)->add(seconds => 1); $timely_start = $balance->start if $timely_start < $balance->start; @@ -675,16 +720,23 @@ sub _add_interval { sub _get_notopup_expiration { my %params = @_; - my($contract,$notopup_discard_intervals,$interval_unit)= @params{qw/contract notopup_discard_intervals interval_unit/}; + my($contract,$start_mode,$notopup_discard_intervals,$interval_unit,$last_balance)= @params{qw/contract $start_mode notopup_discard_intervals interval_unit last_balance/}; my $notopup_expiration = undef; if ($notopup_discard_intervals) { #take the start of the latest interval where a topup occured, #add the allowed number+1 of the current package' intervals. #the balance is discarded if the start of the next package #exceed this calculated expiration date. - my $last_balance_w_topup = $contract->contract_balances->search({ topup_count => { '>' => 0 } },{ order_by => { '-desc' => 'end'},})->first; - $last_balance_w_topup = $contract->contract_balances->search(undef,{ order_by => { '-asc' => 'start'},})->first unless $last_balance_w_topup; - $notopup_expiration = _add_interval($last_balance_w_topup->start,$interval_unit,$notopup_discard_intervals + 1) if $last_balance_w_topup; + my $last_balance_w_topup; + if ($last_balance) { + $last_balance_w_topup = $last_balance; + } else { + $last_balance_w_topup = $contract->contract_balances->search({ topup_count => { '>' => 0 } },{ order_by => { '-desc' => 'end'},})->first; + $last_balance_w_topup = $contract->contract_balances->search(undef,{ order_by => { '-asc' => 'start'},})->first unless $last_balance_w_topup; + $notopup_discard_intervals += 1; + } + $notopup_expiration = _add_interval($last_balance_w_topup->start,$interval_unit,$notopup_discard_intervals, + _START_MODE_PRESERVE_EOM->{$start_mode} ? $contract->create_timestamp // $contract->modify_timestamp : undef) if $last_balance_w_topup; } return $notopup_expiration; } @@ -744,13 +796,11 @@ sub underrun_update_balance { $underrun_lock_threshold = $package->underrun_lock_threshold; $underrun_profile_threshold = $package->underrun_profile_threshold; } + my $update = {}; if (_ENABLE_UNDERRUN_LOCK && defined $underrun_lock_threshold && $balance->cash_balance >= $underrun_lock_threshold && $new_cash_balance < $underrun_lock_threshold) { if (defined $package->underrun_lock_level) { set_subscriber_lock_level(c => $c, contract => $contract, lock_level => $package->underrun_lock_level); - $balance->update({ - underrun_lock => $now, - }); - $balance->discard_changes(); + $update->{underrun_lock} = $now; } } if (_ENABLE_UNDERRUN_PROFILES && defined $underrun_profile_threshold && $balance->cash_balance >= $underrun_profile_threshold && $new_cash_balance < $underrun_profile_threshold) { @@ -762,12 +812,14 @@ sub underrun_update_balance { stime => $now, profiles => 'underrun_profiles', now => $now) > 0) { - $balance->update({ - underrun_profiles => $now, - }); - $balance->discard_changes(); + $update->{underrun_profiles} = $now; } } + if ((scalar keys %$update) > 0) { + $balance->update($update); + $balance->discard_changes(); + } + return $balance; } diff --git a/t/api-rest/api-balanceintervals.t b/t/api-rest/api-balanceintervals.t index 1453759168..de9b6f3479 100644 --- a/t/api-rest/api-balanceintervals.t +++ b/t/api-rest/api-balanceintervals.t @@ -17,6 +17,7 @@ use Storable; use Text::Table; use Text::Wrap; $Text::Wrap::columns = 58; +#use Sys::CpuAffinity; use JSON::PP; use LWP::Debug; @@ -232,6 +233,7 @@ my $gantt_events; if (_get_allow_fake_client_time() && $enable_profile_packages) { + #goto SKIP; #goto THREADED; { my $package = _create_profile_package('create','hour',1); @@ -851,6 +853,81 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) { _set_time(); } + + { + + my $profile_underrun = _create_billing_profile('UNDERRUN_NOTOPUP_INF'); + my $profile_initial = _create_billing_profile('INITIAL_NOTOPUP_INF'); + my $package = _create_profile_package('topup_interval','month',1, notopup_discard_intervals => 3, + initial_balance => 1, carry_over_mode => 'carry_over', + initial_profiles => [{ profile_id => $profile_initial->{id}, }, ], + underrun_lock_threshold => 1, + underrun_lock_level => 4, + underrun_profile_threshold => 1, underrun_profiles => [{ profile_id => $profile_underrun->{id}, }, ],); + + _set_time(NGCP::Panel::Utils::DateTime::from_string('2015-01-30 13:00:00')); + my $customer = _create_customer($package); + my $subscriber = _create_subscriber($customer); + #my $v_notopup = _create_voucher(10,'notopup'.$t); + + _set_time(NGCP::Panel::Utils::DateTime::from_string('2015-02-17 13:00:00')); + + #_perform_topup_voucher($subscriber,$v_notopup); + _check_interval_history($customer,[ + { start => '~2015-01-30 13:00:00', stop => $infinite_future, cash => 0.01, profile => $profile_initial->{id} }, + ]); + is(_get_customer($customer)->{billing_profile_id},$profile_initial->{id},'check customer actual billing profile id'); + is(_get_subscriber_lock_level($subscriber),undef,"check subscriber id " . $subscriber->{id} . " lock level"); + + _set_time(NGCP::Panel::Utils::DateTime::from_string('2015-06-01 13:00:00')); + + _check_interval_history($customer,[ + { start => '~2015-01-30 13:00:00', stop => $infinite_future, cash => 0.00, profile => $profile_initial->{id} }, + ]); + is(_get_customer($customer)->{billing_profile_id},$profile_underrun->{id},'check customer actual billing profile id'); + is(_get_subscriber_lock_level($subscriber),4,"check subscriber id " . $subscriber->{id} . " lock level"); + + _set_time(); + } + + #SKIP: + { + + my $profile_underrun = _create_billing_profile('UNDERRUN_NOTOPUP_TIM'); + my $profile_initial = _create_billing_profile('INITIAL_NOTOPUP_TIM'); + my $package = _create_profile_package('topup_interval','month',1, + initial_balance => 1, carry_over_mode => 'carry_over_timely', + initial_profiles => [{ profile_id => $profile_initial->{id}, }, ], + timely_duration_unit => 'month', + timely_duration_value => 1, + underrun_lock_threshold => 1, + underrun_lock_level => 4, + underrun_profile_threshold => 1, underrun_profiles => [{ profile_id => $profile_underrun->{id}, }, ],); + + _set_time(NGCP::Panel::Utils::DateTime::from_string('2015-01-30 13:00:00')); + my $customer = _create_customer($package); + my $subscriber = _create_subscriber($customer); + #my $v_notopup = _create_voucher(10,'notopup'.$t); + + _set_time(NGCP::Panel::Utils::DateTime::from_string('2015-02-17 13:00:00')); + + #_perform_topup_voucher($subscriber,$v_notopup); + _check_interval_history($customer,[ + { start => '~2015-01-30 13:00:00', stop => $infinite_future, cash => 0.01, profile => $profile_initial->{id} }, + ]); + is(_get_customer($customer)->{billing_profile_id},$profile_initial->{id},'check customer actual billing profile id'); + is(_get_subscriber_lock_level($subscriber),undef,"check subscriber id " . $subscriber->{id} . " lock level"); + + _set_time(NGCP::Panel::Utils::DateTime::from_string('2015-03-01 13:00:00')); + + _check_interval_history($customer,[ + { start => '~2015-01-30 13:00:00', stop => $infinite_future, cash => 0.00, profile => $profile_initial->{id} }, + ]); + is(_get_customer($customer)->{billing_profile_id},$profile_underrun->{id},'check customer actual billing profile id'); + is(_get_subscriber_lock_level($subscriber),4,"check subscriber id " . $subscriber->{id} . " lock level"); + + _set_time(); + } THREADED: { @@ -898,42 +975,42 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) { 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_c = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact9); + #my $t_c = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact9); my $intervals_a = $t_a->join(); my $intervals_b = $t_b->join(); - my $intervals_c = $t_c->join(); + #my $intervals_c = $t_c->join(); my $t2 = time; #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_b->{total_count},3,"check total count of thread b results"); - is($intervals_c->{total_count},scalar (grep { $_->{contact_id} == $custcontact9->{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_desc = $intervals_b->{_embedded}->{'ngcp:customerbalances'}; if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare customerbalances collection results of threaded requests deeply')) { diag(Dumper({asc => $got_asc, desc => $got_desc})); } ok($t2 - $t1 > 2*$delay,'expected delay to assume customerbalances requests were processed after another'); - ok($t2 - $t1 < 3*$delay,'expected delay to assume only required contracts were locked'); + #ok($t2 - $t1 < 3*$delay,'expected delay to assume only required contracts were locked'); $t1 = time; $t_a = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact2); - $t_b = threads->create(\&_fetch_customerbalances_worker,$delay,'id','desc',$custcontact2); - $t_c = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact2); + $t_b = threads->create(\&_fetch_customerbalances_worker,$delay,'id','desc',$custcontact9); + #$t_c = threads->create(\&_fetch_customerbalances_worker,$delay,'id','asc',$custcontact2); $intervals_a = $t_a->join(); $intervals_b = $t_b->join(); - $intervals_c = $t_c->join(); + #$intervals_c = $t_c->join(); $t2 = time; 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_c->{total_count},3,"check total count of thread c results"); + is($intervals_b->{total_count},scalar (grep { $_->{contact_id} == $custcontact9->{id} } values %customer_map),"check total count of thread b results"); + #is($intervals_c->{total_count},3,"check total count of thread c results"); - ok($t2 - $t1 > 3*$delay,'expected delay to assume customerbalances requests were processed after another'); + ok($t2 - $t1 < 2*$delay,'expected delay to assume only required contracts were locked'); } else { diag('allow_delay_commit not set, skipping ...'); } - + if (_get_allow_delay_commit()) { _set_time(NGCP::Panel::Utils::DateTime::current_local->subtract(months => 3)); _create_customers_threaded(3,undef,undef,$custcontact9); @@ -941,18 +1018,18 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) { _set_time(); my $t1 = time; - my $delay = 20; #15; + my $delay = 10; #15; 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_c = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact9); + #my $t_c = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact9); my $intervals_a = $t_a->join(); my $intervals_b = $t_b->join(); - my $intervals_c = $t_c->join(); + #my $intervals_c = $t_c->join(); my $t2 = time; 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_c->{total_count},scalar (grep { $_->{contact_id} == $custcontact9->{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_asc = $intervals_a->{_embedded}->{'ngcp:balanceintervals'}; my $got_desc = $intervals_b->{_embedded}->{'ngcp:balanceintervals'}; @@ -960,28 +1037,28 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) { diag(Dumper({asc => $got_asc, desc => $got_desc})); } ok($t2 - $t1 > 2*$delay,'expected delay to assume balanceintervals requests were processed after another'); - ok($t2 - $t1 < 3*$delay,'expected delay to assume only required contracts were locked'); + #ok($t2 - $t1 < 3*$delay,'expected delay to assume only required contracts were locked'); $t1 = time; $t_a = threads->create(\&_fetch_intervals_worker,$delay,'id','asc',$custcontact3); - $t_b = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact3); - $t_c = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact3); + $t_b = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact9); + #$t_c = threads->create(\&_fetch_intervals_worker,$delay,'id','desc',$custcontact3); $intervals_a = $t_a->join(); $intervals_b = $t_b->join(); - $intervals_c = $t_c->join(); + #$intervals_c = $t_c->join(); $t2 = time; 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_c->{total_count},3,"check total count of thread c results"); + is($intervals_b->{total_count},scalar (grep { $_->{contact_id} == $custcontact9->{id} } values %customer_map),"check total count of thread b results"); + #is($intervals_c->{total_count},3,"check total count of thread c results"); - ok($t2 - $t1 > 3*$delay,'expected delay to assume balanceintervals requests were processed after another'); + ok($t2 - $t1 < 2*$delay,'expected delay to assume only required contracts were locked'); } else { 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')); @@ -989,66 +1066,71 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) { _create_customers_threaded(3,2,$package,$custcontact4); my $t1 = time; - my $delay = 20.0; #15.0; #10.0; #2.0; + my $delay = 10.0; #15.0; #10.0; #2.0; 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_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact9); + #my $t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact9); my $prefs_a = $t_a->join(); my $prefs_b = $t_b->join(); - my $prefs_c = $t_c->join(); + #my $prefs_c = $t_c->join(); my $t2 = time; 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_c->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{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_desc = $prefs_b->{_embedded}->{'ngcp:subscriberpreferences'}; if (!is_deeply($got_desc,[ reverse @{ $got_asc } ],'compare subscriber preference collection results of threaded requests deeply')) { diag(Dumper({asc => $got_asc, desc => $got_desc})); } ok($t2 - $t1 > 2*$delay,'expected delay to assume subscriberpreferences requests were processed after another'); - ok($t2 - $t1 < 3*$delay,'expected delay to assume only required contracts were locked'); + #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_preferences_worker,$delay,'id','asc',$custcontact4); + #$t_b = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact9); + ##$t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact9); + #$prefs_a = $t_a->join(); + #$prefs_b = $t_b->join(); + ##$prefs_c = $t_c->join(); + #$t2 = time; + #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},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{id} } values %subscriber_map),"check total count of thread b results"); + #$got_asc = $prefs_a->{_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')) { + # diag(Dumper({asc => $got_asc, desc => $got_desc})); + #} + #ok($t2 - $t1 > 2*$delay,'expected delay to assume subscriberpreferences 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_preferences_worker,$delay,'id','asc',$custcontact4); - $t_b = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact4); - $t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact9); + $t_b = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact9); + #$t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact4); $prefs_a = $t_a->join(); $prefs_b = $t_b->join(); - $prefs_c = $t_c->join(); + #$prefs_c = $t_c->join(); $t2 = time; + 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_c->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{id} } values %subscriber_map),"check total count of thread c results"); + is($prefs_b->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{id} } values %subscriber_map),"check total count of thread b results"); + #is($prefs_c->{total_count},2*3,"check total count of thread c results"); $got_asc = $prefs_a->{_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')) { - diag(Dumper({asc => $got_asc, desc => $got_desc})); - } - ok($t2 - $t1 > 2*$delay,'expected delay to assume subscriberpreferences 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"); + is($got_asc->[$i]->{lock},4,"check if subscriber is locked now"); } - $t1 = time; - $t_a = threads->create(\&_fetch_preferences_worker,$delay,'id','asc',$custcontact4); - $t_b = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact4); - $t_c = threads->create(\&_fetch_preferences_worker,$delay,'id','desc',$custcontact4); - $prefs_a = $t_a->join(); - $prefs_b = $t_b->join(); - $prefs_c = $t_c->join(); - $t2 = time; - - 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_c->{total_count},2*3,"check total count of thread c results"); - ok($t2 - $t1 > 3*$delay,'expected delay to assume subscriberpreferences requests were processed after another'); + ok($t2 - $t1 < 2*$delay,'expected delay to assume only required contracts were locked'); $t1 = time; $t_a = threads->create(\&_fetch_preferences_worker,$delay,'id','asc',$custcontact4); @@ -1068,7 +1150,7 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) { } else { 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')); @@ -1076,66 +1158,70 @@ if (_get_allow_fake_client_time() && $enable_profile_packages) { _create_customers_threaded(3,2,$package,$custcontact5); my $t1 = time; - my $delay = 20.0; #15.0; #10.0; #2.0; + my $delay = 10.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 $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 $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"); + #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'); + #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',$custcontact9); + ##$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); + $t_b = threads->create(\&_fetch_subscribers_worker,$delay,'id','desc',$custcontact9); + #$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(); + #$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'); + is($subs_b->{total_count},scalar (grep { $customer_map{$_->{customer_id}}->{contact_id} == $custcontact9->{id} } values %subscriber_map),"check total count of thread b results"); + #is($subs_c->{total_count},2*3,"check total count of thread c results"); + $got_asc = $subs_a->{_embedded}->{'ngcp:subscribers'}; + for (my $i = 0; $i < 2*3; $i++) { + is($got_asc->[$i]->{lock},4,"check if subscriber is locked now"); + } + ok($t2 - $t1 < 2*$delay,'expected delay to assume only required contracts were locked'); $t1 = time; $t_a = threads->create(\&_fetch_subscribers_worker,$delay,'id','asc',$custcontact5); @@ -1465,6 +1551,18 @@ sub _create_customer { } +sub _get_customer { + my $customer = shift; + $req = HTTP::Request->new('GET', $uri.'/api/customers/'.$customer->{id}); + $req->header('X-Fake-Clienttime' => _get_fake_clienttime_now()); + $req->header('X-Request-Identifier' => $req_identifier) if $req_identifier; + $res = $ua->request($req); + is($res->code, 200, "fetch customer id " . $customer->{id}); + $customer = JSON::from_json($res->decoded_content); + $customer_map{$customer->{id}} = threads::shared::shared_clone($customer); + return $customer; +} + sub _switch_package { my ($customer,$package) = @_;