Refactor user_actions insert/update/delete statements with Mojo::Pg
This commit is contained in:
parent
ecedc6a4f2
commit
8ad05720a2
2 changed files with 235 additions and 253 deletions
486
lib/Travelynx.pm
486
lib/Travelynx.pm
|
@ -242,58 +242,6 @@ sub startup {
|
|||
);
|
||||
}
|
||||
);
|
||||
$self->attr(
|
||||
action_set_sched_time_query => sub {
|
||||
my ($self) = @_;
|
||||
|
||||
# TODO (re-)initialize all automatically added journeys with edited = 0
|
||||
# and use it as a bit field to precisely indicate which fields have
|
||||
# been edited. -> ".. set edited = edited | 1", "... | 2" etc.
|
||||
# The action_id check is redundant, but better safe than sorry
|
||||
return $self->app->dbh->prepare(
|
||||
qq{
|
||||
update user_actions
|
||||
set sched_time = to_timestamp(?), edited = edited | 1
|
||||
where id = ? and action_id = ?
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
$self->attr(
|
||||
action_set_real_time_query => sub {
|
||||
my ($self) = @_;
|
||||
|
||||
# The action_id check is redundant, but better safe than sorry
|
||||
return $self->app->dbh->prepare(
|
||||
qq{
|
||||
update user_actions
|
||||
set real_time = to_timestamp(?), edited = edited | 2
|
||||
where id = ? and action_id = ?
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
$self->attr(
|
||||
action_query => sub {
|
||||
my ($self) = @_;
|
||||
|
||||
return $self->app->dbh->prepare(
|
||||
qq{
|
||||
insert into user_actions (
|
||||
user_id, action_id, station_id, action_time, edited,
|
||||
train_type, train_line, train_no, train_id,
|
||||
sched_time, real_time,
|
||||
route, messages
|
||||
) values (
|
||||
?, ?, ?, to_timestamp(?), ?,
|
||||
?, ?, ?, ?,
|
||||
to_timestamp(?), to_timestamp(?),
|
||||
?, ?
|
||||
)
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
$self->attr(
|
||||
dbh => sub {
|
||||
my ($self) = @_;
|
||||
|
@ -394,19 +342,6 @@ sub startup {
|
|||
);
|
||||
}
|
||||
);
|
||||
$self->attr(
|
||||
drop_journey_query => sub {
|
||||
my ($self) = @_;
|
||||
|
||||
return $self->app->dbh->prepare(
|
||||
qq{
|
||||
delete from user_actions
|
||||
where user_id = ?
|
||||
and (id = ? or id = ?)
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
$self->attr(
|
||||
get_userid_query => sub {
|
||||
my ($self) = @_;
|
||||
|
@ -640,60 +575,65 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
|||
return ( undef, undef, 'Unbekannter Zielbahnhof' );
|
||||
}
|
||||
|
||||
say $dep_station->[0];
|
||||
say $dep_station->[1];
|
||||
say $arr_station->[0];
|
||||
say $arr_station->[1];
|
||||
my $checkin_id;
|
||||
my $checkout_id;
|
||||
|
||||
my $success = $self->app->action_query->execute(
|
||||
$uid,
|
||||
$self->app->action_type->{checkin},
|
||||
$self->get_station_id(
|
||||
ds100 => $dep_station->[0],
|
||||
name => $dep_station->[1],
|
||||
),
|
||||
DateTime->now( time_zone => 'Europe/Berlin' )->epoch,
|
||||
0x0f,
|
||||
$opt{train_type},
|
||||
$opt{train_line},
|
||||
$opt{train_no},
|
||||
undef,
|
||||
$opt{sched_departure}->epoch,
|
||||
$opt{rt_departure} ? $opt{rt_departure}->epoch : undef,
|
||||
undef, undef
|
||||
);
|
||||
if ( not $success ) {
|
||||
my $err = $self->app->action_query->errstr;
|
||||
$self->app->log->error(
|
||||
"add_journey($uid, checkin): INSERT failed: $err");
|
||||
return ( undef, undef, 'INSERT failed: ' . $err );
|
||||
}
|
||||
my $checkin_id = $self->app->action_query->last_insert_id;
|
||||
eval {
|
||||
$checkin_id = $self->pg->db->insert(
|
||||
'user_actions',
|
||||
{
|
||||
user_id => $uid,
|
||||
action_id => $self->app->action_type->{checkin},
|
||||
station_id => $self->get_station_id(
|
||||
ds100 => $dep_station->[0],
|
||||
name => $dep_station->[1],
|
||||
),
|
||||
action_time =>
|
||||
DateTime->now( time_zone => 'Europe/Berlin' ),
|
||||
edited => 0x0f,
|
||||
train_type => $opt{train_type},
|
||||
train_line => $opt{train_line},
|
||||
train_no => $opt{train_no},
|
||||
sched_time => $opt{sched_departure},
|
||||
real_time => $opt{rt_departure},
|
||||
},
|
||||
{ returning => 'id' }
|
||||
)->hash->{id};
|
||||
};
|
||||
|
||||
$success = $self->app->action_query->execute(
|
||||
$uid,
|
||||
$self->app->action_type->{checkout},
|
||||
$self->get_station_id(
|
||||
ds100 => $arr_station->[0],
|
||||
name => $arr_station->[1],
|
||||
),
|
||||
DateTime->now( time_zone => 'Europe/Berlin' )->epoch,
|
||||
0x0f,
|
||||
$opt{train_type},
|
||||
$opt{train_line},
|
||||
$opt{train_no},
|
||||
undef,
|
||||
$opt{sched_arrival}->epoch,
|
||||
$opt{rt_arrival} ? $opt{rt_arrival}->epoch : undef,
|
||||
undef, undef
|
||||
);
|
||||
if ( not $success ) {
|
||||
my $err = $self->app->action_query->errstr;
|
||||
if ($@) {
|
||||
$self->app->log->error(
|
||||
"add_journey($uid, checkout): INSERT failed: $err");
|
||||
return ( undef, undef, 'INSERT failed: ' . $err );
|
||||
"add_journey($uid, checkin): INSERT failed: $@");
|
||||
return ( undef, undef, 'INSERT failed: ' . $@ );
|
||||
}
|
||||
|
||||
eval {
|
||||
$checkout_id = $self->pg->db->insert(
|
||||
'user_actions',
|
||||
{
|
||||
user_id => $uid,
|
||||
action_id => $self->app->action_type->{checkout},
|
||||
station_id => $self->get_station_id(
|
||||
ds100 => $arr_station->[0],
|
||||
name => $arr_station->[1],
|
||||
),
|
||||
action_time =>
|
||||
DateTime->now( time_zone => 'Europe/Berlin' ),
|
||||
edited => 0x0f,
|
||||
train_type => $opt{train_type},
|
||||
train_line => $opt{train_line},
|
||||
train_no => $opt{train_no},
|
||||
sched_time => $opt{sched_arrival},
|
||||
real_time => $opt{rt_arrival},
|
||||
},
|
||||
{ returnning => 'id' }
|
||||
)->hash->{id};
|
||||
};
|
||||
if ($@) {
|
||||
$self->app->log->error(
|
||||
"add_journey($uid, checkout): INSERT failed: $@");
|
||||
return ( undef, undef, 'INSERT failed: ' . $@ );
|
||||
}
|
||||
my $checkout_id = $self->app->action_query->last_insert_id;
|
||||
return ( $checkin_id, $checkout_id, undef );
|
||||
}
|
||||
);
|
||||
|
@ -730,40 +670,43 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
|||
$self->app->action_type->{cancelled_to} );
|
||||
}
|
||||
|
||||
my $success = $self->app->action_query->execute(
|
||||
$self->current_user->{id},
|
||||
$action_id,
|
||||
$self->get_station_id(
|
||||
ds100 => $status->{station_ds100},
|
||||
name => $status->{station_name}
|
||||
),
|
||||
DateTime->now( time_zone => 'Europe/Berlin' )->epoch,
|
||||
0,
|
||||
$train->type,
|
||||
$train->line_no,
|
||||
$train->train_no,
|
||||
$train->train_id,
|
||||
$train->sched_departure->epoch,
|
||||
$train->departure->epoch,
|
||||
join( '|', $train->route ),
|
||||
join(
|
||||
'|',
|
||||
map {
|
||||
( $_->[0] ? $_->[0]->epoch : q{} ) . ':'
|
||||
. $_->[1]
|
||||
} $train->messages
|
||||
)
|
||||
);
|
||||
if ( defined $success ) {
|
||||
return ( $train, undef );
|
||||
}
|
||||
else {
|
||||
eval {
|
||||
$self->pg->db->insert(
|
||||
'user_actions',
|
||||
{
|
||||
user_id => $self->current_user->{id},
|
||||
action_id => $action_id,
|
||||
station_id => $self->get_station_id(
|
||||
ds100 => $status->{station_ds100},
|
||||
name => $status->{station_name}
|
||||
),
|
||||
action_time =>
|
||||
DateTime->now( time_zone => 'Europe/Berlin' ),
|
||||
edited => 0,
|
||||
train_type => $train->type,
|
||||
train_line => $train->line_no,
|
||||
train_no => $train->train_no,
|
||||
train_id => $train->train_id,
|
||||
sched_time => $train->sched_departure,
|
||||
real_time => $train->departure,
|
||||
route => join( '|', $train->route ),
|
||||
messages => join(
|
||||
'|',
|
||||
map {
|
||||
( $_->[0] ? $_->[0]->epoch : q{} ) . ':'
|
||||
. $_->[1]
|
||||
} $train->messages
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
if ($@) {
|
||||
my $uid = $self->current_user->{id};
|
||||
my $err = $self->app->action_query->errstr;
|
||||
$self->app->log->error(
|
||||
"Checkin($uid, $action_id): INSERT failed: $err");
|
||||
return ( undef, 'INSERT failed: ' . $err );
|
||||
"Checkin($uid, $action_id): INSERT failed: $@");
|
||||
return ( undef, 'INSERT failed: ' . $@ );
|
||||
}
|
||||
return ( $train, undef );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -876,72 +819,73 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
|||
= first { $_->train_id eq $train_id } @{ $status->{results} };
|
||||
if ( not defined $train ) {
|
||||
if ($force) {
|
||||
my $success = $self->app->action_query->execute(
|
||||
$self->current_user->{id},
|
||||
$action_id,
|
||||
$self->get_station_id(
|
||||
ds100 => $status->{station_ds100},
|
||||
name => $status->{station_name}
|
||||
),
|
||||
$now->epoch,
|
||||
0, undef, undef, undef, undef,
|
||||
undef, undef, undef, undef
|
||||
);
|
||||
if ( defined $success ) {
|
||||
$self->invalidate_stats_cache;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
my $uid = $self->current_user->{id};
|
||||
my $err = $self->app->action_query->errstr;
|
||||
$self->app->log->error(
|
||||
"Force checkout($uid, $action_id): INSERT failed: $err"
|
||||
eval {
|
||||
$self->pg->db->insert(
|
||||
'user_actions',
|
||||
{
|
||||
user_id => $self->current_user->{id},
|
||||
action_id => $action_id,
|
||||
station_id => $self->get_station_id(
|
||||
ds100 => $status->{station_ds100},
|
||||
name => $status->{station_name}
|
||||
),
|
||||
action_time => $now,
|
||||
edited => 0
|
||||
}
|
||||
);
|
||||
return 'INSERT failed: ' . $err;
|
||||
};
|
||||
if ($@) {
|
||||
my $uid = $self->current_user->{id};
|
||||
$self->app->log->error(
|
||||
"Force checkout($uid, $action_id): INSERT failed: $@"
|
||||
);
|
||||
return 'INSERT failed: ' . $@;
|
||||
}
|
||||
$self->invalidate_stats_cache;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
return "Train ${train_id} not found";
|
||||
}
|
||||
}
|
||||
else {
|
||||
my $success = $self->app->action_query->execute(
|
||||
$self->current_user->{id},
|
||||
$action_id,
|
||||
$self->get_station_id(
|
||||
ds100 => $status->{station_ds100},
|
||||
name => $status->{station_name}
|
||||
),
|
||||
$now->epoch,
|
||||
0,
|
||||
$train->type,
|
||||
$train->line_no,
|
||||
$train->train_no,
|
||||
$train->train_id,
|
||||
$train->sched_arrival
|
||||
? $train->sched_arrival->epoch
|
||||
: undef,
|
||||
$train->arrival ? $train->arrival->epoch : undef,
|
||||
join( '|', $train->route ),
|
||||
join(
|
||||
'|',
|
||||
map {
|
||||
( $_->[0] ? $_->[0]->epoch : q{} ) . ':'
|
||||
. $_->[1]
|
||||
} $train->messages
|
||||
)
|
||||
);
|
||||
if ( defined $success ) {
|
||||
$self->invalidate_stats_cache;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
eval {
|
||||
$self->pg->db->insert(
|
||||
'user_actions',
|
||||
{
|
||||
user_id => $self->current_user->{id},
|
||||
action_id => $action_id,
|
||||
station_id => $self->get_station_id(
|
||||
ds100 => $status->{station_ds100},
|
||||
name => $status->{station_name}
|
||||
),
|
||||
action_time => $now,
|
||||
edited => 0,
|
||||
train_type => $train->type,
|
||||
train_line => $train->line_no,
|
||||
train_no => $train->train_no,
|
||||
train_id => $train->train_id,
|
||||
sched_time => $train->sched_arrival,
|
||||
real_time => $train->arrival,
|
||||
route => join( '|', $train->route ),
|
||||
messages => join(
|
||||
'|',
|
||||
map {
|
||||
( $_->[0] ? $_->[0]->epoch : q{} ) . ':'
|
||||
. $_->[1]
|
||||
} $train->messages
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
if ($@) {
|
||||
my $uid = $self->current_user->{id};
|
||||
my $err = $self->app->action_query->errstr;
|
||||
$self->app->log->error(
|
||||
"Checkout($uid, $action_id): INSERT failed: $err");
|
||||
return 'INSERT failed: ' . $err;
|
||||
"Checkout($uid, $action_id): INSERT failed: $@");
|
||||
return 'INSERT failed: ' . $@;
|
||||
}
|
||||
$self->invalidate_stats_cache;
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -949,45 +893,75 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
|||
$self->helper(
|
||||
'update_journey_part' => sub {
|
||||
my ( $self, $checkin_id, $checkout_id, $key, $value ) = @_;
|
||||
my ( $query, $id, $action_type );
|
||||
my $rows;
|
||||
|
||||
if ( $key eq 'sched_departure' ) {
|
||||
$query = $self->app->action_set_sched_time_query;
|
||||
$id = $checkin_id;
|
||||
$action_type = $self->app->action_type->{checkin};
|
||||
}
|
||||
elsif ( $key eq 'rt_departure' ) {
|
||||
$query = $self->app->action_set_real_time_query;
|
||||
$id = $checkin_id;
|
||||
$action_type = $self->app->action_type->{checkin};
|
||||
}
|
||||
elsif ( $key eq 'sched_arrival' ) {
|
||||
$query = $self->app->action_set_sched_time_query;
|
||||
$id = $checkout_id;
|
||||
$action_type = $self->app->action_type->{checkout};
|
||||
}
|
||||
elsif ( $key eq 'rt_arrival' ) {
|
||||
$query = $self->app->action_set_real_time_query;
|
||||
$id = $checkout_id;
|
||||
$action_type = $self->app->action_type->{checkout};
|
||||
}
|
||||
else {
|
||||
$self->app->log->error(
|
||||
"update_journey_part(id = $id): Invalid key $key");
|
||||
return 'Internal Error';
|
||||
}
|
||||
|
||||
my $success = $query->execute( $value, $id, $action_type );
|
||||
if ($success) {
|
||||
if ( $query->rows == 1 ) {
|
||||
return undef;
|
||||
eval {
|
||||
my $db = $self->pg->db;
|
||||
if ( $key eq 'sched_departure' ) {
|
||||
$rows = $db->update(
|
||||
'user_actions',
|
||||
{
|
||||
sched_time => $value,
|
||||
},
|
||||
{
|
||||
id => $checkin_id,
|
||||
action_id => $self->app->action_type->{checkin},
|
||||
}
|
||||
)->rows;
|
||||
}
|
||||
return 'UPDATE failed: did not match any journey part';
|
||||
elsif ( $key eq 'rt_departure' ) {
|
||||
$rows = $db->update(
|
||||
'user_actions',
|
||||
{
|
||||
real_time => $value,
|
||||
},
|
||||
{
|
||||
id => $checkin_id,
|
||||
action_id => $self->app->action_type->{checkin},
|
||||
}
|
||||
)->rows;
|
||||
}
|
||||
elsif ( $key eq 'sched_arrival' ) {
|
||||
$rows = $db->update(
|
||||
'user_actions',
|
||||
{
|
||||
sched_time => $value,
|
||||
},
|
||||
{
|
||||
id => $checkout_id,
|
||||
action_id => $self->app->action_type->{checkout},
|
||||
}
|
||||
)->rows;
|
||||
}
|
||||
elsif ( $key eq 'rt_arrival' ) {
|
||||
$rows = $db->update(
|
||||
'user_actions',
|
||||
{
|
||||
real_time => $value,
|
||||
},
|
||||
{
|
||||
id => $checkout_id,
|
||||
action_id => $self->app->action_type->{checkout},
|
||||
}
|
||||
)->rows;
|
||||
}
|
||||
else {
|
||||
$self->app->log->error(
|
||||
"update_journey_part($checkin_id, $checkout_id): Invalid key $key"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
$self->app->log->error(
|
||||
"update_journey_part($checkin_id, $checkout_id): UPDATE failed: $@"
|
||||
);
|
||||
return 'UPDATE failed: ' . $@;
|
||||
}
|
||||
my $err = $query->errstr;
|
||||
$self->app->log->error(
|
||||
"update_journey_part($id): UPDATE failed: $err");
|
||||
return 'UPDATE failed: ' . $err;
|
||||
if ( $rows == 1 ) {
|
||||
return undef;
|
||||
}
|
||||
return 'UPDATE failed: did not match any journey part';
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1221,22 +1195,30 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
|||
{
|
||||
return 'Invalid journey data';
|
||||
}
|
||||
my $query = $self->app->drop_journey_query;
|
||||
my $success = $query->execute( $uid, $checkin_id, $checkout_id );
|
||||
if ($success) {
|
||||
if ( $query->rows == 2 ) {
|
||||
$self->invalidate_stats_cache( $journey->{checkout} );
|
||||
return undef;
|
||||
}
|
||||
else {
|
||||
return
|
||||
sprintf( 'Deleted %d rows, expected 2', $query->rows );
|
||||
}
|
||||
|
||||
my $rows;
|
||||
eval {
|
||||
$rows = $self->pg->db->delete(
|
||||
'user_actions',
|
||||
{
|
||||
user_id => $uid,
|
||||
id => [ $checkin_id, $checkout_id ]
|
||||
}
|
||||
)->rows;
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
$self->app->log->error(
|
||||
"Delete($uid, $checkin_id, $checkout_id): DELETE failed: $@"
|
||||
);
|
||||
return 'DELETE failed: ' . $@;
|
||||
}
|
||||
my $err = $self->app->drop_journey_query->errstr;
|
||||
$self->app->log->error(
|
||||
"Delete($uid, $checkin_id, $checkout_id): DELETE failed: $err");
|
||||
return 'DELETE failed: ' . $err;
|
||||
|
||||
if ( $rows == 2 ) {
|
||||
$self->invalidate_stats_cache( $journey->{checkout} );
|
||||
return undef;
|
||||
}
|
||||
return sprintf( 'Deleted %d rows, expected 2', $rows );
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -470,7 +470,7 @@ sub edit_journey {
|
|||
$error = $self->update_journey_part(
|
||||
$journey->{ids}[0],
|
||||
$journey->{ids}[1],
|
||||
$key, $datetime->epoch
|
||||
$key, $datetime
|
||||
);
|
||||
if ($error) {
|
||||
last;
|
||||
|
|
Loading…
Reference in a new issue