convert checkout to promises (checkout_p)
This commit is contained in:
parent
c0754f9e87
commit
38ad42b42c
3 changed files with 347 additions and 256 deletions
125
lib/Travelynx.pm
125
lib/Travelynx.pm
|
@ -588,7 +588,7 @@ sub startup {
|
|||
);
|
||||
|
||||
$self->helper(
|
||||
'checkout' => sub {
|
||||
'checkout_p' => sub {
|
||||
my ( $self, %opt ) = @_;
|
||||
|
||||
my $station = $opt{station};
|
||||
|
@ -596,34 +596,29 @@ sub startup {
|
|||
my $arr_eva = $opt{arr_eva};
|
||||
my $with_related = $opt{with_related} // 0;
|
||||
my $force = $opt{force};
|
||||
my $uid = $opt{uid};
|
||||
my $uid = $opt{uid} // $self->current_user->{id};
|
||||
my $db = $opt{db} // $self->pg->db;
|
||||
my $status = $self->iris->get_departures(
|
||||
station => $station,
|
||||
lookbehind => 120,
|
||||
lookahead => 180,
|
||||
with_related => $with_related,
|
||||
);
|
||||
$uid //= $self->current_user->{id};
|
||||
my $user = $self->get_user_status( $uid, $db );
|
||||
my $train_id = $user->{train_id};
|
||||
|
||||
my $promise = Mojo::Promise->new;
|
||||
|
||||
if ( not $station ) {
|
||||
$self->app->log->error("Checkout($uid): station is empty");
|
||||
return ( 1, 'BUG: Checkout station is empty.' );
|
||||
return $promise->resolve( 1,
|
||||
'BUG: Checkout station is empty.' );
|
||||
}
|
||||
|
||||
if ( not $user->{checked_in} and not $user->{cancelled} ) {
|
||||
return ( 0, 'You are not checked into any train' );
|
||||
}
|
||||
if ( $status->{errstr} and not $force ) {
|
||||
return ( 1, $status->{errstr} );
|
||||
return $promise->resolve( 0,
|
||||
'You are not checked into any train' );
|
||||
}
|
||||
|
||||
if ( $dep_eva and $dep_eva != $user->{dep_eva} ) {
|
||||
return ( 0, 'race condition' );
|
||||
return $promise->resolve( 0, 'race condition' );
|
||||
}
|
||||
if ( $arr_eva and $arr_eva != $user->{arr_eva} ) {
|
||||
return ( 0, 'race condition' );
|
||||
return $promise->resolve( 0, 'race condition' );
|
||||
}
|
||||
|
||||
my $now = DateTime->now( time_zone => 'Europe/Berlin' );
|
||||
|
@ -632,23 +627,21 @@ sub startup {
|
|||
with_data => 1
|
||||
);
|
||||
|
||||
# Note that a train may pass the same station several times.
|
||||
# Notable example: S41 / S42 ("Ringbahn") both starts and
|
||||
# terminates at Berlin Südkreuz
|
||||
my ($train) = List::Util::first {
|
||||
$_->train_id eq $train_id
|
||||
and $_->sched_arrival
|
||||
and $_->sched_arrival->epoch > $user->{sched_departure}->epoch
|
||||
}
|
||||
@{ $status->{results} };
|
||||
|
||||
$train //= List::Util::first { $_->train_id eq $train_id }
|
||||
@{ $status->{results} };
|
||||
$self->iris->get_departures_p(
|
||||
station => $station,
|
||||
lookbehind => 120,
|
||||
lookahead => 180,
|
||||
with_related => $with_related,
|
||||
)->then(
|
||||
sub {
|
||||
my ($status) = @_;
|
||||
|
||||
my $new_checkout_station_id = $status->{station_eva};
|
||||
|
||||
# Store the intended checkout station regardless of this operation's
|
||||
# success.
|
||||
# TODO for with_related == 1, the correct EVA may be different
|
||||
# and should be fetched from $train later on
|
||||
$self->in_transit->set_arrival_eva(
|
||||
uid => $uid,
|
||||
db => $db,
|
||||
|
@ -667,10 +660,24 @@ sub startup {
|
|||
);
|
||||
}
|
||||
|
||||
# Note that a train may pass the same station several times.
|
||||
# Notable example: S41 / S42 ("Ringbahn") both starts and
|
||||
# terminates at Berlin Südkreuz
|
||||
my $train = List::Util::first {
|
||||
$_->train_id eq $train_id
|
||||
and $_->sched_arrival
|
||||
and $_->sched_arrival->epoch
|
||||
> $user->{sched_departure}->epoch
|
||||
}
|
||||
@{ $status->{results} };
|
||||
|
||||
$train //= List::Util::first { $_->train_id eq $train_id }
|
||||
@{ $status->{results} };
|
||||
|
||||
if ( not defined $train ) {
|
||||
|
||||
# Arrival time via IRIS is unknown, so the train probably has not
|
||||
# arrived yet. Fall back to HAFAS.
|
||||
# Arrival time via IRIS is unknown, so the train probably
|
||||
# has not arrived yet. Fall back to HAFAS.
|
||||
# TODO support cases where $station is EVA or DS100 code
|
||||
if (
|
||||
my $station_data
|
||||
|
@ -682,14 +689,16 @@ sub startup {
|
|||
if ( $station_data->{sched_arr} ) {
|
||||
my $sched_arr
|
||||
= epoch_to_dt( $station_data->{sched_arr} );
|
||||
my $rt_arr = epoch_to_dt( $station_data->{rt_arr} );
|
||||
my $rt_arr
|
||||
= epoch_to_dt( $station_data->{rt_arr} );
|
||||
if ( $rt_arr->epoch == 0 ) {
|
||||
$rt_arr = $sched_arr->clone;
|
||||
if ( $station_data->{arr_delay}
|
||||
and $station_data->{arr_delay} =~ m{^\d+$} )
|
||||
and $station_data->{arr_delay}
|
||||
=~ m{^\d+$} )
|
||||
{
|
||||
$rt_arr->add(
|
||||
minutes => $station_data->{arr_delay} );
|
||||
$rt_arr->add( minutes =>
|
||||
$station_data->{arr_delay} );
|
||||
}
|
||||
}
|
||||
$self->in_transit->set_arrival_times(
|
||||
|
@ -706,10 +715,10 @@ sub startup {
|
|||
if ( not $opt{in_transaction} ) {
|
||||
$self->run_hook( $uid, 'update' );
|
||||
}
|
||||
return ( 1, undef );
|
||||
$promise->resolve( 1, undef );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
my $has_arrived = 0;
|
||||
|
||||
eval {
|
||||
|
@ -719,7 +728,10 @@ sub startup {
|
|||
$tx = $db->begin;
|
||||
}
|
||||
|
||||
if ( defined $train and not $train->arrival and not $force ) {
|
||||
if ( defined $train
|
||||
and not $train->arrival
|
||||
and not $force )
|
||||
{
|
||||
my $train_no = $train->train_no;
|
||||
die("Train ${train_no} has no arrival timestamp\n");
|
||||
}
|
||||
|
@ -731,10 +743,12 @@ sub startup {
|
|||
route => [ $self->iris->route_diff($train) ]
|
||||
);
|
||||
|
||||
$has_arrived = $train->arrival->epoch < $now->epoch ? 1 : 0;
|
||||
$has_arrived
|
||||
= $train->arrival->epoch < $now->epoch ? 1 : 0;
|
||||
if ($has_arrived) {
|
||||
my @unknown_stations
|
||||
= $self->stations->grep_unknown( $train->route );
|
||||
= $self->stations->grep_unknown(
|
||||
$train->route );
|
||||
if (@unknown_stations) {
|
||||
$self->app->log->warn(
|
||||
sprintf(
|
||||
|
@ -767,7 +781,8 @@ sub startup {
|
|||
|
||||
my $cache_ts = $now->clone;
|
||||
if ( $journey->{real_departure}
|
||||
=~ m{ ^ (?<year> \d{4} ) - (?<month> \d{2} ) }x )
|
||||
=~ m{ ^ (?<year> \d{4} ) - (?<month> \d{2} ) }x
|
||||
)
|
||||
{
|
||||
$cache_ts->set(
|
||||
year => $+{year},
|
||||
|
@ -780,7 +795,9 @@ sub startup {
|
|||
uid => $uid
|
||||
);
|
||||
}
|
||||
elsif ( defined $train and $train->arrival_is_cancelled ) {
|
||||
elsif ( defined $train
|
||||
and $train->arrival_is_cancelled )
|
||||
{
|
||||
|
||||
# This branch is only taken if the deparure was not cancelled,
|
||||
# i.e., if the train was supposed to go here but got
|
||||
|
@ -808,20 +825,34 @@ sub startup {
|
|||
|
||||
if ($@) {
|
||||
$self->app->log->error("Checkout($uid): $@");
|
||||
return ( 1, 'Checkout error: ' . $@ );
|
||||
$promise->resolve( 1, 'Checkout error: ' . $@ );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $has_arrived or $force ) {
|
||||
if ( not $opt{in_transaction} ) {
|
||||
$self->run_hook( $uid, 'checkout' );
|
||||
}
|
||||
return ( 0, undef );
|
||||
$promise->resolve( 0, undef );
|
||||
return;
|
||||
}
|
||||
if ( not $opt{in_transaction} ) {
|
||||
$self->run_hook( $uid, 'update' );
|
||||
$self->add_route_timestamps( $uid, $train, 0, 1 );
|
||||
}
|
||||
return ( 1, undef );
|
||||
$promise->resolve( 1, undef );
|
||||
return;
|
||||
|
||||
}
|
||||
)->catch(
|
||||
sub {
|
||||
my ($err) = @_;
|
||||
$promise->resolve( 1, $err );
|
||||
return;
|
||||
}
|
||||
)->wait;
|
||||
|
||||
return $promise;
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1788,13 +1819,17 @@ sub startup {
|
|||
)->then(
|
||||
sub {
|
||||
$self->log->debug("... handled origin");
|
||||
my ( undef, $err ) = $self->checkout(
|
||||
return $self->checkout_p(
|
||||
station => $traewelling->{arr_eva},
|
||||
train_id => 0,
|
||||
uid => $uid,
|
||||
in_transaction => 1,
|
||||
db => $db
|
||||
);
|
||||
}
|
||||
)->then(
|
||||
sub {
|
||||
my ( undef, $err ) = @_;
|
||||
if ($err) {
|
||||
$self->log->debug("... error: $err");
|
||||
return Mojo::Promise->reject($err);
|
||||
|
|
|
@ -88,13 +88,13 @@ sub run {
|
|||
|
||||
# check out (adds a cancelled journey and resets journey state
|
||||
# to checkin
|
||||
$self->app->checkout(
|
||||
$self->app->checkout_p(
|
||||
station => $arr,
|
||||
force => 1,
|
||||
force => 2,
|
||||
dep_eva => $dep,
|
||||
arr_eva => $arr,
|
||||
uid => $uid
|
||||
);
|
||||
)->wait;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -155,13 +155,13 @@ sub run {
|
|||
|
||||
# check out (adds a cancelled journey and resets journey state
|
||||
# to destination selection)
|
||||
$self->app->checkout(
|
||||
$self->app->checkout_p(
|
||||
station => $arr,
|
||||
force => 0,
|
||||
dep_eva => $dep,
|
||||
arr_eva => $arr,
|
||||
uid => $uid
|
||||
);
|
||||
)->wait;
|
||||
}
|
||||
else {
|
||||
$self->app->add_route_timestamps(
|
||||
|
@ -174,21 +174,24 @@ sub run {
|
|||
}
|
||||
}
|
||||
elsif ( $entry->{real_arr_ts} ) {
|
||||
my ( undef, $error ) = $self->app->checkout(
|
||||
my ( undef, $error ) = $self->app->checkout_p(
|
||||
station => $arr,
|
||||
force => 1,
|
||||
force => 2,
|
||||
dep_eva => $dep,
|
||||
arr_eva => $arr,
|
||||
uid => $uid
|
||||
);
|
||||
if ($error) {
|
||||
die("${error}\n");
|
||||
)->catch(
|
||||
sub {
|
||||
my ($error) = @_;
|
||||
$self->app->log->error("work($uid)/arrival: $@");
|
||||
$errors += 1;
|
||||
}
|
||||
)->wait;
|
||||
}
|
||||
};
|
||||
if ($@) {
|
||||
$errors += 1;
|
||||
$self->app->log->error("work($uid)/arrival: $@");
|
||||
$errors += 1;
|
||||
}
|
||||
|
||||
eval { }
|
||||
|
|
|
@ -622,17 +622,26 @@ sub travel_action {
|
|||
if ( $params->{action} eq 'checkin' ) {
|
||||
|
||||
my $status = $self->get_user_status;
|
||||
my $promise;
|
||||
|
||||
if ( $status->{checked_in}
|
||||
and $status->{arr_eva}
|
||||
and $status->{arrival_countdown} <= 0 )
|
||||
{
|
||||
$self->checkout( station => $status->{arr_eva} );
|
||||
$promise = $self->checkout_p( station => $status->{arr_eva} );
|
||||
}
|
||||
else {
|
||||
$promise = Mojo::Promise->resolve;
|
||||
}
|
||||
|
||||
$self->render_later;
|
||||
$self->checkin_p(
|
||||
$promise->then(
|
||||
sub {
|
||||
return $self->checkin_p(
|
||||
station => $params->{station},
|
||||
train_id => $params->{train}
|
||||
);
|
||||
}
|
||||
)->then(
|
||||
sub {
|
||||
my $destination = $params->{dest};
|
||||
|
@ -648,18 +657,27 @@ sub travel_action {
|
|||
|
||||
# Silently ignore errors -- if they are permanent, the user will see
|
||||
# them when selecting the destination manually.
|
||||
my ( $still_checked_in, undef ) = $self->checkout(
|
||||
return $self->checkout_p(
|
||||
station => $destination,
|
||||
force => 0
|
||||
);
|
||||
}
|
||||
)->then(
|
||||
sub {
|
||||
my ( $still_checked_in, undef ) = @_;
|
||||
if ( my $destination = $params->{dest} ) {
|
||||
my $station_link = '/s/' . $destination;
|
||||
$self->render(
|
||||
json => {
|
||||
success => 1,
|
||||
redirect_to => $still_checked_in ? '/' : $station_link,
|
||||
redirect_to => $still_checked_in
|
||||
? '/'
|
||||
: $station_link,
|
||||
},
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
)->catch(
|
||||
sub {
|
||||
my ($error) = @_;
|
||||
|
@ -673,10 +691,13 @@ sub travel_action {
|
|||
)->wait;
|
||||
}
|
||||
elsif ( $params->{action} eq 'checkout' ) {
|
||||
my ( $still_checked_in, $error ) = $self->checkout(
|
||||
$self->render_later;
|
||||
$self->checkout_p(
|
||||
station => $params->{station},
|
||||
force => $params->{force}
|
||||
);
|
||||
)->then(
|
||||
sub {
|
||||
my ( $still_checked_in, $error ) = @_;
|
||||
my $station_link = '/s/' . $params->{station};
|
||||
|
||||
if ($error) {
|
||||
|
@ -691,10 +712,26 @@ sub travel_action {
|
|||
$self->render(
|
||||
json => {
|
||||
success => 1,
|
||||
redirect_to => $still_checked_in ? '/' : $station_link,
|
||||
redirect_to => $still_checked_in
|
||||
? '/'
|
||||
: $station_link,
|
||||
},
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
)->catch(
|
||||
sub {
|
||||
my ($error) = @_;
|
||||
$self->render(
|
||||
json => {
|
||||
success => 0,
|
||||
error => $error,
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
)->wait;
|
||||
}
|
||||
elsif ( $params->{action} eq 'undo' ) {
|
||||
my $status = $self->get_user_status;
|
||||
|
@ -747,11 +784,13 @@ sub travel_action {
|
|||
)->wait;
|
||||
}
|
||||
elsif ( $params->{action} eq 'cancelled_to' ) {
|
||||
my ( undef, $error ) = $self->checkout(
|
||||
$self->render_later;
|
||||
$self->checkout_p(
|
||||
station => $params->{station},
|
||||
force => 1
|
||||
);
|
||||
|
||||
)->then(
|
||||
sub {
|
||||
my ( undef, $error ) = @_;
|
||||
if ($error) {
|
||||
$self->render(
|
||||
json => {
|
||||
|
@ -768,6 +807,20 @@ sub travel_action {
|
|||
},
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
)->catch(
|
||||
sub {
|
||||
my ($error) = @_;
|
||||
$self->render(
|
||||
json => {
|
||||
success => 0,
|
||||
error => $error,
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
)->wait;
|
||||
}
|
||||
elsif ( $params->{action} eq 'delete' ) {
|
||||
my $error = $self->journeys->delete(
|
||||
|
|
Loading…
Reference in a new issue