From b3b0a055b9b4c3ab332f75070ce1fa80a3638105 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 24 Nov 2019 20:29:52 +0100 Subject: [PATCH] improve get_user_travels performance, most notably when rendering map only create DateTime objects when needed --- lib/Travelynx.pm | 99 +++++++++++---------- lib/Travelynx/Controller/Passengerrights.pm | 34 +++---- lib/Travelynx/Controller/Traveling.pm | 45 +++++----- t/02-registration.t | 4 + templates/history_map.html.ep | 2 +- templates/landingpage.html.ep | 2 +- 6 files changed, 101 insertions(+), 85 deletions(-) diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index 387d4de..a07d851 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -783,8 +783,9 @@ sub startup { my $rows; my $journey = $self->get_journey( - db => $db, - journey_id => $journey_id, + db => $db, + journey_id => $journey_id, + with_datetime => 1, ); eval { @@ -1504,8 +1505,8 @@ sub startup { # are really deleting the right journey and the user isn't just # playing around with POST requests. if ( $journey->{id} != $journey_id - or $journey->{checkin}->epoch != $checkin_epoch - or $journey->{checkout}->epoch != $checkout_epoch ) + or $journey->{checkin_ts} != $checkin_epoch + or $journey->{checkout_ts} != $checkout_epoch ) { return 'Invalid journey data'; } @@ -1527,7 +1528,8 @@ sub startup { } if ( $rows == 1 ) { - $self->invalidate_stats_cache( $journey->{rt_departure} ); + $self->invalidate_stats_cache( + epoch_to_dt( $journey->{rt_dep_ts} ) ); return undef; } return sprintf( 'Deleted %d rows, expected 1', $rows ); @@ -2377,24 +2379,34 @@ sub startup { for my $entry ( $res->expand->hashes->each ) { my $ref = { - id => $entry->{journey_id}, - type => $entry->{train_type}, - line => $entry->{train_line}, - no => $entry->{train_no}, - from_name => $entry->{dep_name}, - checkin => epoch_to_dt( $entry->{checkin_ts} ), - sched_departure => epoch_to_dt( $entry->{sched_dep_ts} ), - rt_departure => epoch_to_dt( $entry->{real_dep_ts} ), - to_name => $entry->{arr_name}, - checkout => epoch_to_dt( $entry->{checkout_ts} ), - sched_arrival => epoch_to_dt( $entry->{sched_arr_ts} ), - rt_arrival => epoch_to_dt( $entry->{real_arr_ts} ), - messages => $entry->{messages}, - route => $entry->{route}, - edited => $entry->{edited}, - user_data => $entry->{user_data}, + id => $entry->{journey_id}, + type => $entry->{train_type}, + line => $entry->{train_line}, + no => $entry->{train_no}, + from_name => $entry->{dep_name}, + checkin_ts => $entry->{checkin_ts}, + sched_dep_ts => $entry->{sched_dep_ts}, + rt_dep_ts => $entry->{real_dep_ts}, + to_name => $entry->{arr_name}, + checkout_ts => $entry->{checkout_ts}, + sched_arr_ts => $entry->{sched_arr_ts}, + rt_arr_ts => $entry->{real_arr_ts}, + messages => $entry->{messages}, + route => $entry->{route}, + edited => $entry->{edited}, + 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} ) { $ref->{cancelled} = $entry->{cancelled}; my @parsed_messages; @@ -2404,13 +2416,12 @@ sub startup { } $ref->{messages} = [ reverse @parsed_messages ]; $ref->{sched_duration} - = $ref->{sched_arrival}->epoch - ? $ref->{sched_arrival}->epoch - - $ref->{sched_departure}->epoch + = $ref->{sched_arr_ts} + ? $ref->{sched_arr_ts} - $ref->{sched_dep_ts} : undef; $ref->{rt_duration} - = $ref->{rt_arrival}->epoch - ? $ref->{rt_arrival}->epoch - $ref->{rt_departure}->epoch + = $ref->{rt_arr_ts} + ? $ref->{rt_arr_ts} - $ref->{rt_dep_ts} : undef; my ( $km_route, $km_beeline, $skip ) = $self->get_travel_distance( $ref->{from_name}, @@ -2960,7 +2971,7 @@ sub startup { my $num_journeys = 0; my @inconsistencies; - my $next_departure = epoch_to_dt(0); + my $next_departure = 0; for my $journey (@journeys) { $num_trains++; @@ -2974,42 +2985,36 @@ sub startup { if ( $journey->{rt_duration} and $journey->{rt_duration} > 0 ) { $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 - += ( $journey->{rt_departure}->epoch - - $journey->{sched_departure}->epoch ) / 60; + += ( $journey->{rt_dep_ts} - $journey->{sched_dep_ts} ) + / 60; } - if ( $journey->{sched_arrival} and $journey->{rt_arrival} ) { + if ( $journey->{sched_arr_ts} and $journey->{rt_arr_ts} ) { $delay_arr - += ( $journey->{rt_arrival}->epoch - - $journey->{sched_arrival}->epoch ) / 60; + += ( $journey->{rt_arr_ts} - $journey->{sched_arr_ts} ) + / 60; } # Note that journeys are sorted from recent to older entries - if ( $journey->{rt_arrival} - and $next_departure->epoch - and $next_departure->epoch - $journey->{rt_arrival}->epoch - < ( 60 * 60 ) ) + if ( $journey->{rt_arr_ts} + and $next_departure + and $next_departure - $journey->{rt_arr_ts} < ( 60 * 60 ) ) { - if ( - $next_departure->epoch - $journey->{rt_arrival}->epoch - < 0 ) - { + if ( $next_departure - $journey->{rt_arr_ts} < 0 ) { push( @inconsistencies, - $next_departure->strftime('%d.%m.%Y %H:%M') ); + epoch_to_dt($next_departure) + ->strftime('%d.%m.%Y %H:%M') ); } else { $interchange_real - += ( $next_departure->epoch - - $journey->{rt_arrival}->epoch ) - / 60; + += ( $next_departure - $journey->{rt_arr_ts} ) / 60; } } else { $num_journeys++; } - $next_departure = $journey->{rt_departure}; + $next_departure = $journey->{rt_dep_ts}; } return { km_route => $km_route, diff --git a/lib/Travelynx/Controller/Passengerrights.pm b/lib/Travelynx/Controller/Passengerrights.pm index 0170ed5..d6ed39c 100644 --- a/lib/Travelynx/Controller/Passengerrights.pm +++ b/lib/Travelynx/Controller/Passengerrights.pm @@ -53,6 +53,7 @@ sub mark_substitute_connection { my @substitute_candidates = reverse $self->get_user_travels( after => $journey->{sched_departure}->clone->subtract( hours => 1 ), before => $journey->{sched_departure}->clone->add( hours => 12 ), + with_datetime => 1, ); my ( $first_substitute, $last_substitute ); @@ -76,8 +77,7 @@ sub mark_substitute_connection { $journey->{from_substitute} = $first_substitute; $journey->{to_substitute} = $last_substitute; $journey->{substitute_delay} - = ( $last_substitute->{rt_arrival}->epoch - - $journey->{sched_arrival}->epoch ) / 60; + = ( $last_substitute->{rt_arr_ts} - $journey->{sched_ar_ts} ) / 60; } } @@ -88,8 +88,9 @@ sub list_candidates { my $range_start = $now->clone->subtract( months => 6 ); my @journeys = $self->get_user_travels( - after => $range_start, - before => $now + after => $range_start, + before => $now, + with_datetime => 1, ); @journeys = grep { $_->{sched_arrival}->epoch and $_->{rt_arrival}->epoch } @journeys; @@ -112,9 +113,10 @@ sub list_candidates { @journeys = grep { $_->{delay} >= 60 or $_->{connection_missed} } @journeys; my @cancelled = $self->get_user_travels( - after => $range_start, - before => $now, - cancelled => 1 + after => $range_start, + before => $now, + cancelled => 1, + with_datetime => 1, ); for my $journey (@cancelled) { @@ -126,8 +128,8 @@ sub list_candidates { $self->mark_substitute_connection($journey); if ( not $journey->{has_substitute} - or $journey->{to_substitute}->{rt_arrival}->epoch - - $journey->{sched_arrival}->epoch >= 3600 ) + or $journey->{to_substitute}->{rt_arr_ts} - $journey->{sched_arr_ts} + >= 3600 ) { push( @journeys, $journey ); } @@ -162,9 +164,10 @@ sub generate { } my $journey = $self->get_journey( - uid => $uid, - journey_id => $journey_id, - verbose => 1, + uid => $uid, + journey_id => $journey_id, + verbose => 1, + with_datetime => 1, ); if ( not $journey ) { @@ -185,9 +188,10 @@ sub generate { } elsif ( $journey->{delay} < 120 ) { my @connections = $self->get_user_travels( - uid => $uid, - after => $journey->{rt_arrival}, - before => $journey->{rt_arrival}->clone->add( hours => 2 ) + uid => $uid, + after => $journey->{rt_arrival}, + before => $journey->{rt_arrival}->clone->add( hours => 2 ), + with_datetime => 1, ); if (@connections) { $self->mark_if_missed_connection( $journey, $connections[-1] ); diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index c05586a..56de0fb 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -397,7 +397,10 @@ sub redirect_to_station { sub cancelled { my ($self) = @_; - my @journeys = $self->get_user_travels( cancelled => 1 ); + my @journeys = $self->get_user_travels( + cancelled => 1, + with_datetime => 1 + ); $self->respond_to( json => { json => [@journeys] }, @@ -419,7 +422,6 @@ sub map_history { 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; if ( not @journeys ) { @@ -428,8 +430,6 @@ sub map_history { with_map => 1, station_coordinates => [], station_pairs => [], - range_from => 0, - range_to => 0, ); return; } @@ -494,8 +494,6 @@ sub map_history { with_map => 1, station_coordinates => \@station_coordinates, 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. 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 { my $interval_start = DateTime->new( @@ -529,8 +527,9 @@ sub yearly_history { ); my $interval_end = $interval_start->clone->add( years => 1 ); @journeys = $self->get_user_travels( - after => $interval_start, - before => $interval_end + after => $interval_start, + before => $interval_end, + with_datetime => 1 ); $stats = $self->get_journey_stats( year => $year ); } @@ -572,7 +571,7 @@ sub monthly_history { and $month < 13 ) ) { - @journeys = $self->get_user_travels; + @journeys = $self->get_user_travels( with_datetime => 1 ); } else { my $interval_start = DateTime->new( @@ -586,8 +585,9 @@ sub monthly_history { ); my $interval_end = $interval_start->clone->add( months => 1 ); @journeys = $self->get_user_travels( - after => $interval_start, - before => $interval_end + after => $interval_start, + before => $interval_end, + with_datetime => 1 ); $stats = $self->get_journey_stats( year => $year, @@ -632,9 +632,10 @@ sub journey_details { } my $journey = $self->get_journey( - uid => $uid, - journey_id => $journey_id, - verbose => 1, + uid => $uid, + journey_id => $journey_id, + verbose => 1, + with_datetime => 1, ); if ($journey) { @@ -669,8 +670,9 @@ sub edit_journey { } my $journey = $self->get_journey( - uid => $uid, - journey_id => $journey_id + uid => $uid, + journey_id => $journey_id, + with_datetime => 1, ); if ( not $journey ) { @@ -732,10 +734,11 @@ sub edit_journey { if ( not $error ) { $journey = $self->get_journey( - uid => $uid, - db => $db, - journey_id => $journey_id, - verbose => 1 + uid => $uid, + db => $db, + journey_id => $journey_id, + verbose => 1, + with_datetime => 1, ); $error = $self->journey_sanity_check($journey); } diff --git a/t/02-registration.t b/t/02-registration.t index 0d324b0..2258d9a 100644 --- a/t/02-registration.t +++ b/t/02-registration.t @@ -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 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 = $t->ua->get('/journey/add')->res->dom->at('input[name=csrf_token]') ->attr('value'); diff --git a/templates/history_map.html.ep b/templates/history_map.html.ep index 90b5647..97b2276 100644 --- a/templates/history_map.html.ep +++ b/templates/history_map.html.ep @@ -1,7 +1,7 @@
% if (@{$station_coordinates}) { - Zugfahrten zwischen <%= $range_from->strftime('%d.%m.%Y') %> und <%= $range_to->strftime('%d.%m.%Y') %> + Alle bisherigen Zugfahrten % } % else { Keine Zugfahrten gefunden. diff --git a/templates/landingpage.html.ep b/templates/landingpage.html.ep index ad80350..fd71f9c 100644 --- a/templates/landingpage.html.ep +++ b/templates/landingpage.html.ep @@ -70,7 +70,7 @@

Letzte Fahrten

- %= 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 {