improve get_user_travels performance, most notably when rendering map
only create DateTime objects when needed
This commit is contained in:
parent
9782cee53d
commit
b3b0a055b9
6 changed files with 101 additions and 85 deletions
|
@ -783,8 +783,9 @@ sub startup {
|
||||||
my $rows;
|
my $rows;
|
||||||
|
|
||||||
my $journey = $self->get_journey(
|
my $journey = $self->get_journey(
|
||||||
db => $db,
|
db => $db,
|
||||||
journey_id => $journey_id,
|
journey_id => $journey_id,
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
eval {
|
eval {
|
||||||
|
@ -1504,8 +1505,8 @@ sub startup {
|
||||||
# are really deleting the right journey and the user isn't just
|
# are really deleting the right journey and the user isn't just
|
||||||
# playing around with POST requests.
|
# playing around with POST requests.
|
||||||
if ( $journey->{id} != $journey_id
|
if ( $journey->{id} != $journey_id
|
||||||
or $journey->{checkin}->epoch != $checkin_epoch
|
or $journey->{checkin_ts} != $checkin_epoch
|
||||||
or $journey->{checkout}->epoch != $checkout_epoch )
|
or $journey->{checkout_ts} != $checkout_epoch )
|
||||||
{
|
{
|
||||||
return 'Invalid journey data';
|
return 'Invalid journey data';
|
||||||
}
|
}
|
||||||
|
@ -1527,7 +1528,8 @@ sub startup {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $rows == 1 ) {
|
if ( $rows == 1 ) {
|
||||||
$self->invalidate_stats_cache( $journey->{rt_departure} );
|
$self->invalidate_stats_cache(
|
||||||
|
epoch_to_dt( $journey->{rt_dep_ts} ) );
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
return sprintf( 'Deleted %d rows, expected 1', $rows );
|
return sprintf( 'Deleted %d rows, expected 1', $rows );
|
||||||
|
@ -2377,24 +2379,34 @@ sub startup {
|
||||||
for my $entry ( $res->expand->hashes->each ) {
|
for my $entry ( $res->expand->hashes->each ) {
|
||||||
|
|
||||||
my $ref = {
|
my $ref = {
|
||||||
id => $entry->{journey_id},
|
id => $entry->{journey_id},
|
||||||
type => $entry->{train_type},
|
type => $entry->{train_type},
|
||||||
line => $entry->{train_line},
|
line => $entry->{train_line},
|
||||||
no => $entry->{train_no},
|
no => $entry->{train_no},
|
||||||
from_name => $entry->{dep_name},
|
from_name => $entry->{dep_name},
|
||||||
checkin => epoch_to_dt( $entry->{checkin_ts} ),
|
checkin_ts => $entry->{checkin_ts},
|
||||||
sched_departure => epoch_to_dt( $entry->{sched_dep_ts} ),
|
sched_dep_ts => $entry->{sched_dep_ts},
|
||||||
rt_departure => epoch_to_dt( $entry->{real_dep_ts} ),
|
rt_dep_ts => $entry->{real_dep_ts},
|
||||||
to_name => $entry->{arr_name},
|
to_name => $entry->{arr_name},
|
||||||
checkout => epoch_to_dt( $entry->{checkout_ts} ),
|
checkout_ts => $entry->{checkout_ts},
|
||||||
sched_arrival => epoch_to_dt( $entry->{sched_arr_ts} ),
|
sched_arr_ts => $entry->{sched_arr_ts},
|
||||||
rt_arrival => epoch_to_dt( $entry->{real_arr_ts} ),
|
rt_arr_ts => $entry->{real_arr_ts},
|
||||||
messages => $entry->{messages},
|
messages => $entry->{messages},
|
||||||
route => $entry->{route},
|
route => $entry->{route},
|
||||||
edited => $entry->{edited},
|
edited => $entry->{edited},
|
||||||
user_data => $entry->{user_data},
|
user_data => $entry->{user_data},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if ( $opt{with_datetime} ) {
|
||||||
|
$ref->{checkin} = epoch_to_dt( $ref->{checkin_ts} );
|
||||||
|
$ref->{sched_departure}
|
||||||
|
= epoch_to_dt( $ref->{sched_dep_ts} );
|
||||||
|
$ref->{rt_departure} = epoch_to_dt( $ref->{rt_dep_ts} );
|
||||||
|
$ref->{checkout} = epoch_to_dt( $ref->{checkout_ts} );
|
||||||
|
$ref->{sched_arrival} = epoch_to_dt( $ref->{sched_arr_ts} );
|
||||||
|
$ref->{rt_arrival} = epoch_to_dt( $ref->{rt_arr_ts} );
|
||||||
|
}
|
||||||
|
|
||||||
if ( $opt{verbose} ) {
|
if ( $opt{verbose} ) {
|
||||||
$ref->{cancelled} = $entry->{cancelled};
|
$ref->{cancelled} = $entry->{cancelled};
|
||||||
my @parsed_messages;
|
my @parsed_messages;
|
||||||
|
@ -2404,13 +2416,12 @@ sub startup {
|
||||||
}
|
}
|
||||||
$ref->{messages} = [ reverse @parsed_messages ];
|
$ref->{messages} = [ reverse @parsed_messages ];
|
||||||
$ref->{sched_duration}
|
$ref->{sched_duration}
|
||||||
= $ref->{sched_arrival}->epoch
|
= $ref->{sched_arr_ts}
|
||||||
? $ref->{sched_arrival}->epoch
|
? $ref->{sched_arr_ts} - $ref->{sched_dep_ts}
|
||||||
- $ref->{sched_departure}->epoch
|
|
||||||
: undef;
|
: undef;
|
||||||
$ref->{rt_duration}
|
$ref->{rt_duration}
|
||||||
= $ref->{rt_arrival}->epoch
|
= $ref->{rt_arr_ts}
|
||||||
? $ref->{rt_arrival}->epoch - $ref->{rt_departure}->epoch
|
? $ref->{rt_arr_ts} - $ref->{rt_dep_ts}
|
||||||
: undef;
|
: undef;
|
||||||
my ( $km_route, $km_beeline, $skip )
|
my ( $km_route, $km_beeline, $skip )
|
||||||
= $self->get_travel_distance( $ref->{from_name},
|
= $self->get_travel_distance( $ref->{from_name},
|
||||||
|
@ -2960,7 +2971,7 @@ sub startup {
|
||||||
my $num_journeys = 0;
|
my $num_journeys = 0;
|
||||||
my @inconsistencies;
|
my @inconsistencies;
|
||||||
|
|
||||||
my $next_departure = epoch_to_dt(0);
|
my $next_departure = 0;
|
||||||
|
|
||||||
for my $journey (@journeys) {
|
for my $journey (@journeys) {
|
||||||
$num_trains++;
|
$num_trains++;
|
||||||
|
@ -2974,42 +2985,36 @@ sub startup {
|
||||||
if ( $journey->{rt_duration} and $journey->{rt_duration} > 0 ) {
|
if ( $journey->{rt_duration} and $journey->{rt_duration} > 0 ) {
|
||||||
$min_travel_real += $journey->{rt_duration} / 60;
|
$min_travel_real += $journey->{rt_duration} / 60;
|
||||||
}
|
}
|
||||||
if ( $journey->{sched_departure} and $journey->{rt_departure} )
|
if ( $journey->{sched_dep_ts} and $journey->{rt_dep_ts} ) {
|
||||||
{
|
|
||||||
$delay_dep
|
$delay_dep
|
||||||
+= ( $journey->{rt_departure}->epoch
|
+= ( $journey->{rt_dep_ts} - $journey->{sched_dep_ts} )
|
||||||
- $journey->{sched_departure}->epoch ) / 60;
|
/ 60;
|
||||||
}
|
}
|
||||||
if ( $journey->{sched_arrival} and $journey->{rt_arrival} ) {
|
if ( $journey->{sched_arr_ts} and $journey->{rt_arr_ts} ) {
|
||||||
$delay_arr
|
$delay_arr
|
||||||
+= ( $journey->{rt_arrival}->epoch
|
+= ( $journey->{rt_arr_ts} - $journey->{sched_arr_ts} )
|
||||||
- $journey->{sched_arrival}->epoch ) / 60;
|
/ 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Note that journeys are sorted from recent to older entries
|
# Note that journeys are sorted from recent to older entries
|
||||||
if ( $journey->{rt_arrival}
|
if ( $journey->{rt_arr_ts}
|
||||||
and $next_departure->epoch
|
and $next_departure
|
||||||
and $next_departure->epoch - $journey->{rt_arrival}->epoch
|
and $next_departure - $journey->{rt_arr_ts} < ( 60 * 60 ) )
|
||||||
< ( 60 * 60 ) )
|
|
||||||
{
|
{
|
||||||
if (
|
if ( $next_departure - $journey->{rt_arr_ts} < 0 ) {
|
||||||
$next_departure->epoch - $journey->{rt_arrival}->epoch
|
|
||||||
< 0 )
|
|
||||||
{
|
|
||||||
push( @inconsistencies,
|
push( @inconsistencies,
|
||||||
$next_departure->strftime('%d.%m.%Y %H:%M') );
|
epoch_to_dt($next_departure)
|
||||||
|
->strftime('%d.%m.%Y %H:%M') );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$interchange_real
|
$interchange_real
|
||||||
+= ( $next_departure->epoch
|
+= ( $next_departure - $journey->{rt_arr_ts} ) / 60;
|
||||||
- $journey->{rt_arrival}->epoch )
|
|
||||||
/ 60;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$num_journeys++;
|
$num_journeys++;
|
||||||
}
|
}
|
||||||
$next_departure = $journey->{rt_departure};
|
$next_departure = $journey->{rt_dep_ts};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
km_route => $km_route,
|
km_route => $km_route,
|
||||||
|
|
|
@ -53,6 +53,7 @@ sub mark_substitute_connection {
|
||||||
my @substitute_candidates = reverse $self->get_user_travels(
|
my @substitute_candidates = reverse $self->get_user_travels(
|
||||||
after => $journey->{sched_departure}->clone->subtract( hours => 1 ),
|
after => $journey->{sched_departure}->clone->subtract( hours => 1 ),
|
||||||
before => $journey->{sched_departure}->clone->add( hours => 12 ),
|
before => $journey->{sched_departure}->clone->add( hours => 12 ),
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
my ( $first_substitute, $last_substitute );
|
my ( $first_substitute, $last_substitute );
|
||||||
|
@ -76,8 +77,7 @@ sub mark_substitute_connection {
|
||||||
$journey->{from_substitute} = $first_substitute;
|
$journey->{from_substitute} = $first_substitute;
|
||||||
$journey->{to_substitute} = $last_substitute;
|
$journey->{to_substitute} = $last_substitute;
|
||||||
$journey->{substitute_delay}
|
$journey->{substitute_delay}
|
||||||
= ( $last_substitute->{rt_arrival}->epoch
|
= ( $last_substitute->{rt_arr_ts} - $journey->{sched_ar_ts} ) / 60;
|
||||||
- $journey->{sched_arrival}->epoch ) / 60;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +88,9 @@ sub list_candidates {
|
||||||
my $range_start = $now->clone->subtract( months => 6 );
|
my $range_start = $now->clone->subtract( months => 6 );
|
||||||
|
|
||||||
my @journeys = $self->get_user_travels(
|
my @journeys = $self->get_user_travels(
|
||||||
after => $range_start,
|
after => $range_start,
|
||||||
before => $now
|
before => $now,
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
@journeys = grep { $_->{sched_arrival}->epoch and $_->{rt_arrival}->epoch }
|
@journeys = grep { $_->{sched_arrival}->epoch and $_->{rt_arrival}->epoch }
|
||||||
@journeys;
|
@journeys;
|
||||||
|
@ -112,9 +113,10 @@ sub list_candidates {
|
||||||
@journeys = grep { $_->{delay} >= 60 or $_->{connection_missed} } @journeys;
|
@journeys = grep { $_->{delay} >= 60 or $_->{connection_missed} } @journeys;
|
||||||
|
|
||||||
my @cancelled = $self->get_user_travels(
|
my @cancelled = $self->get_user_travels(
|
||||||
after => $range_start,
|
after => $range_start,
|
||||||
before => $now,
|
before => $now,
|
||||||
cancelled => 1
|
cancelled => 1,
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
for my $journey (@cancelled) {
|
for my $journey (@cancelled) {
|
||||||
|
|
||||||
|
@ -126,8 +128,8 @@ sub list_candidates {
|
||||||
$self->mark_substitute_connection($journey);
|
$self->mark_substitute_connection($journey);
|
||||||
|
|
||||||
if ( not $journey->{has_substitute}
|
if ( not $journey->{has_substitute}
|
||||||
or $journey->{to_substitute}->{rt_arrival}->epoch
|
or $journey->{to_substitute}->{rt_arr_ts} - $journey->{sched_arr_ts}
|
||||||
- $journey->{sched_arrival}->epoch >= 3600 )
|
>= 3600 )
|
||||||
{
|
{
|
||||||
push( @journeys, $journey );
|
push( @journeys, $journey );
|
||||||
}
|
}
|
||||||
|
@ -162,9 +164,10 @@ sub generate {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $journey = $self->get_journey(
|
my $journey = $self->get_journey(
|
||||||
uid => $uid,
|
uid => $uid,
|
||||||
journey_id => $journey_id,
|
journey_id => $journey_id,
|
||||||
verbose => 1,
|
verbose => 1,
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( not $journey ) {
|
if ( not $journey ) {
|
||||||
|
@ -185,9 +188,10 @@ sub generate {
|
||||||
}
|
}
|
||||||
elsif ( $journey->{delay} < 120 ) {
|
elsif ( $journey->{delay} < 120 ) {
|
||||||
my @connections = $self->get_user_travels(
|
my @connections = $self->get_user_travels(
|
||||||
uid => $uid,
|
uid => $uid,
|
||||||
after => $journey->{rt_arrival},
|
after => $journey->{rt_arrival},
|
||||||
before => $journey->{rt_arrival}->clone->add( hours => 2 )
|
before => $journey->{rt_arrival}->clone->add( hours => 2 ),
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
if (@connections) {
|
if (@connections) {
|
||||||
$self->mark_if_missed_connection( $journey, $connections[-1] );
|
$self->mark_if_missed_connection( $journey, $connections[-1] );
|
||||||
|
|
|
@ -397,7 +397,10 @@ sub redirect_to_station {
|
||||||
|
|
||||||
sub cancelled {
|
sub cancelled {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
my @journeys = $self->get_user_travels( cancelled => 1 );
|
my @journeys = $self->get_user_travels(
|
||||||
|
cancelled => 1,
|
||||||
|
with_datetime => 1
|
||||||
|
);
|
||||||
|
|
||||||
$self->respond_to(
|
$self->respond_to(
|
||||||
json => { json => [@journeys] },
|
json => { json => [@journeys] },
|
||||||
|
@ -419,7 +422,6 @@ sub map_history {
|
||||||
|
|
||||||
my $location = $self->app->coordinates_by_station;
|
my $location = $self->app->coordinates_by_station;
|
||||||
|
|
||||||
# TODO create map-specific get_user_travels function returning EVA/DS100 station codes?
|
|
||||||
my @journeys = $self->get_user_travels;
|
my @journeys = $self->get_user_travels;
|
||||||
|
|
||||||
if ( not @journeys ) {
|
if ( not @journeys ) {
|
||||||
|
@ -428,8 +430,6 @@ sub map_history {
|
||||||
with_map => 1,
|
with_map => 1,
|
||||||
station_coordinates => [],
|
station_coordinates => [],
|
||||||
station_pairs => [],
|
station_pairs => [],
|
||||||
range_from => 0,
|
|
||||||
range_to => 0,
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -494,8 +494,6 @@ sub map_history {
|
||||||
with_map => 1,
|
with_map => 1,
|
||||||
station_coordinates => \@station_coordinates,
|
station_coordinates => \@station_coordinates,
|
||||||
station_pairs => \@station_pairs,
|
station_pairs => \@station_pairs,
|
||||||
range_from => $first_departure,
|
|
||||||
range_to => $last_departure,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +513,7 @@ sub yearly_history {
|
||||||
# -> Limit time range to avoid accidental DoS.
|
# -> Limit time range to avoid accidental DoS.
|
||||||
if ( not( $year =~ m{ ^ [0-9]{4} $ }x and $year > 1990 and $year < 2100 ) )
|
if ( not( $year =~ m{ ^ [0-9]{4} $ }x and $year > 1990 and $year < 2100 ) )
|
||||||
{
|
{
|
||||||
@journeys = $self->get_user_travels;
|
@journeys = $self->get_user_travels( with_datetime => 1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
my $interval_start = DateTime->new(
|
my $interval_start = DateTime->new(
|
||||||
|
@ -529,8 +527,9 @@ sub yearly_history {
|
||||||
);
|
);
|
||||||
my $interval_end = $interval_start->clone->add( years => 1 );
|
my $interval_end = $interval_start->clone->add( years => 1 );
|
||||||
@journeys = $self->get_user_travels(
|
@journeys = $self->get_user_travels(
|
||||||
after => $interval_start,
|
after => $interval_start,
|
||||||
before => $interval_end
|
before => $interval_end,
|
||||||
|
with_datetime => 1
|
||||||
);
|
);
|
||||||
$stats = $self->get_journey_stats( year => $year );
|
$stats = $self->get_journey_stats( year => $year );
|
||||||
}
|
}
|
||||||
|
@ -572,7 +571,7 @@ sub monthly_history {
|
||||||
and $month < 13 )
|
and $month < 13 )
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@journeys = $self->get_user_travels;
|
@journeys = $self->get_user_travels( with_datetime => 1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
my $interval_start = DateTime->new(
|
my $interval_start = DateTime->new(
|
||||||
|
@ -586,8 +585,9 @@ sub monthly_history {
|
||||||
);
|
);
|
||||||
my $interval_end = $interval_start->clone->add( months => 1 );
|
my $interval_end = $interval_start->clone->add( months => 1 );
|
||||||
@journeys = $self->get_user_travels(
|
@journeys = $self->get_user_travels(
|
||||||
after => $interval_start,
|
after => $interval_start,
|
||||||
before => $interval_end
|
before => $interval_end,
|
||||||
|
with_datetime => 1
|
||||||
);
|
);
|
||||||
$stats = $self->get_journey_stats(
|
$stats = $self->get_journey_stats(
|
||||||
year => $year,
|
year => $year,
|
||||||
|
@ -632,9 +632,10 @@ sub journey_details {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $journey = $self->get_journey(
|
my $journey = $self->get_journey(
|
||||||
uid => $uid,
|
uid => $uid,
|
||||||
journey_id => $journey_id,
|
journey_id => $journey_id,
|
||||||
verbose => 1,
|
verbose => 1,
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($journey) {
|
if ($journey) {
|
||||||
|
@ -669,8 +670,9 @@ sub edit_journey {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $journey = $self->get_journey(
|
my $journey = $self->get_journey(
|
||||||
uid => $uid,
|
uid => $uid,
|
||||||
journey_id => $journey_id
|
journey_id => $journey_id,
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( not $journey ) {
|
if ( not $journey ) {
|
||||||
|
@ -732,10 +734,11 @@ sub edit_journey {
|
||||||
|
|
||||||
if ( not $error ) {
|
if ( not $error ) {
|
||||||
$journey = $self->get_journey(
|
$journey = $self->get_journey(
|
||||||
uid => $uid,
|
uid => $uid,
|
||||||
db => $db,
|
db => $db,
|
||||||
journey_id => $journey_id,
|
journey_id => $journey_id,
|
||||||
verbose => 1
|
verbose => 1,
|
||||||
|
with_datetime => 1,
|
||||||
);
|
);
|
||||||
$error = $self->journey_sanity_check($journey);
|
$error = $self->journey_sanity_check($journey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,6 +237,10 @@ $t->get_ok('/history/2018')->status_is(200)->content_like(qr{62 km})
|
||||||
->content_like(qr{Bei Abfahrt: 00:00 Stunden})
|
->content_like(qr{Bei Abfahrt: 00:00 Stunden})
|
||||||
->content_like(qr{Bei Ankunft: 00:00 Stunden});
|
->content_like(qr{Bei Ankunft: 00:00 Stunden});
|
||||||
|
|
||||||
|
$t->get_ok('/history/map')->status_is(200)
|
||||||
|
->content_like(qr{\[\[51.956[^,]*,7.635[^]]*\],'M.nster\(Westf\)Hbf'\],})
|
||||||
|
->content_like(qr{\[\[51.504[^,]*,7.102[^]]*\],'Gelsenkirchen Hbf'\]});
|
||||||
|
|
||||||
$csrf_token
|
$csrf_token
|
||||||
= $t->ua->get('/journey/add')->res->dom->at('input[name=csrf_token]')
|
= $t->ua->get('/journey/add')->res->dom->at('input[name=csrf_token]')
|
||||||
->attr('value');
|
->attr('value');
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
% if (@{$station_coordinates}) {
|
% if (@{$station_coordinates}) {
|
||||||
Zugfahrten zwischen <%= $range_from->strftime('%d.%m.%Y') %> und <%= $range_to->strftime('%d.%m.%Y') %>
|
Alle bisherigen Zugfahrten
|
||||||
% }
|
% }
|
||||||
% else {
|
% else {
|
||||||
Keine Zugfahrten gefunden.
|
Keine Zugfahrten gefunden.
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1>Letzte Fahrten</h1>
|
<h1>Letzte Fahrten</h1>
|
||||||
%= include '_history_trains', date_format => '%d.%m', journeys => [get_user_travels(limit => 5)];
|
%= include '_history_trains', date_format => '%d.%m', journeys => [get_user_travels(limit => 5, with_datetime => 1)];
|
||||||
% }
|
% }
|
||||||
% else {
|
% else {
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
Loading…
Reference in a new issue