Unverified Commit 0d108e43 authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

work: move DB manipulation to InTransit helper

parent 15b510de
Loading
Loading
Loading
Loading
+32 −107
Original line number Diff line number Diff line
@@ -21,18 +21,14 @@ sub run {
	my $checkin_deadline = $now->clone->subtract( hours => 48 );
	my $json             = JSON->new;

	my $db = $self->app->pg->db;
	my $num_incomplete = $self->app->in_transit->delete_incomplete_checkins(
		earlier_than => $checkin_deadline );

	my $res = $db->delete( 'in_transit',
		{ checkin_time => { '<', $checkin_deadline } } );

	if ( my $rows = $res->rows ) {
		$self->app->log->debug("Removed ${rows} incomplete checkins");
	if ($num_incomplete) {
		$self->app->log->debug("Removed ${num_incomplete} incomplete checkins");
	}

	for my $entry (
		$db->select( 'in_transit_str', '*', { cancelled => 0 } )->hashes->each )
	{
	for my $entry ( $self->app->in_transit->get_all_active ) {

		my $uid      = $entry->{user_id};
		my $dep      = $entry->{dep_eva};
@@ -63,61 +59,26 @@ sub run {
					die("could not find train $train_id at $dep\n");
				}

				# selecting on user_id and train_no avoids a race condition when
				# a user checks into a new train while we are fetching data for
				# their previous journey. In this case, the new train would
				# receive data from the previous journey.
				$db->update(
					'in_transit',
					{
						dep_platform   => $train->platform,
						real_departure => $train->departure,
						route          => $json->encode(
							[ $self->app->iris->route_diff($train) ]
						),
						messages => $json->encode(
							[
								map { [ $_->[0]->epoch, $_->[1] ] }
								  $train->messages
							]
						),
					},
					{
						user_id  => $uid,
						train_no => $train->train_no
					}
				$self->app->in_transit->update_departure(
					uid   => $uid,
					train => $train,
					route => [ $self->app->iris->route_diff($train) ]
				);

				if ( $train->departure_is_cancelled and $arr ) {
					my $checked_in
					  = $self->app->in_transit->update_departure_cancelled(
						uid     => $uid,
						train   => $train,
						dep_eva => $dep,
						arr_eva => $arr,
					  );

					# depending on the amount of users in transit, some time may
					# have passed between fetching $entry from the database and
					# now. Ensure that the user is still checked into this train
					# before calling checkout to mark the cancellation.
					if (
						$db->select(
							'in_transit',
							'count(*) as count',
							{
								user_id             => $uid,
								train_no            => $train->train_no,
								checkin_station_id  => $dep,
								checkout_station_id => $arr,
							}
						)->hash->{count}
					  )
					{
						$db->update(
							'in_transit',
							{
								cancelled => 1,
							},
							{
								user_id             => $uid,
								train_no            => $train->train_no,
								checkin_station_id  => $dep,
								checkout_station_id => $arr,
							}
						);
					# now. Only check out if the user is still checked into this
					# train.
					if ($checked_in) {

                  # check out (adds a cancelled journey and resets journey state
                  # to checkin
@@ -173,50 +134,15 @@ sub run {
					return;
				}

             # selecting on user_id, train_no and checkout_station_id avoids a
             # race condition when a user checks into a new train or changes
             # their destination station while we are fetching times based on no
             # longer valid database entries.
				$db->update(
					'in_transit',
					{
						arr_platform  => $train->platform,
						sched_arrival => $train->sched_arrival,
						real_arrival  => $train->arrival,
						route         => $json->encode(
							[ $self->app->iris->route_diff($train) ]
						),
						messages => $json->encode(
							[
								map { [ $_->[0]->epoch, $_->[1] ] }
								  $train->messages
							]
						),
					},
					{
						user_id             => $uid,
						train_no            => $train->train_no,
						checkout_station_id => $arr
					}
				my $checked_in = $self->app->in_transit->update_arrival(
					uid     => $uid,
					train   => $train,
					route   => [ $self->app->iris->route_diff($train) ],
					arr_eva => $arr,
				);
				if ( $train->arrival_is_cancelled ) {

					# depending on the amount of users in transit, some time may
					# have passed between fetching $entry from the database and
					# now. Ensure that the user is still checked into this train
					# before calling checkout to mark the cancellation.
					if (
						$db->select(
							'in_transit',
							'count(*) as count',
							{
								user_id             => $uid,
								train_no            => $train->train_no,
								checkout_station_id => $arr
							}
						)->hash->{count}
					  )
					{
				if ( $checked_in and $train->arrival_is_cancelled ) {

                  # check out (adds a cancelled journey and resets journey state
                  # to destination selection)
					$self->app->checkout(
@@ -225,7 +151,6 @@ sub run {
						uid     => $uid
					);
				}
				}
				else {
					$self->app->add_route_timestamps( $uid, $train, 0 );
				}
+107 −2
Original line number Diff line number Diff line
package Travelynx::Model::InTransit;

# Copyright (C) 2020 Daniel Friesel
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@@ -69,6 +70,15 @@ sub delete {
	$db->delete( 'in_transit', { user_id => $uid } );
}

sub delete_incomplete_checkins {
	my ( $self, %opt ) = @_;

	my $db = $opt{db} // $self->{pg}->db;

	return $db->delete( 'in_transit',
		{ checkin_time => { '<', $opt{earlier_than} } } )->rows;
}

sub get {
	my ( $self, %opt ) = @_;

@@ -89,6 +99,13 @@ sub get {
	return $res->hash;
}

sub get_all_active {
	my ( $self, %opt ) = @_;
	my $db = $opt{db} // $self->{pg}->db;
	return $db->select( 'in_transit_str', '*', { cancelled => 0 } )
	  ->hashes->each;
}

sub get_checkout_station_id {
	my ( $self, %opt ) = @_;

@@ -252,6 +269,94 @@ sub unset_arrival_data {
	);
}

sub update_departure {
	my ( $self, %opt ) = @_;
	my $uid   = $opt{uid};
	my $db    = $opt{db} // $self->{pg}->db;
	my $train = $opt{train};
	my $json  = JSON->new;

	# selecting on user_id and train_no avoids a race condition if a user checks
	# into a new train while we are fetching data for their previous journey. In
	# this case, the new train would receive data from the previous journey.
	$db->update(
		'in_transit',
		{
			dep_platform   => $train->platform,
			real_departure => $train->departure,
			route          => $json->encode( $opt{route} ),
			messages       => $json->encode(
				[ map { [ $_->[0]->epoch, $_->[1] ] } $train->messages ]
			),
		},
		{
			user_id  => $uid,
			train_no => $train->train_no
		}
	);
}

sub update_departure_cancelled {
	my ( $self, %opt ) = @_;
	my $uid     = $opt{uid};
	my $db      = $opt{db} // $self->{pg}->db;
	my $dep_eva = $opt{dep_eva};
	my $arr_eva = $opt{arr_eva};
	my $train   = $opt{train};

	# depending on the amount of users in transit, some time may
	# have passed between fetching $entry from the database and
	# now. Ensure that the user is still checked into this train
	# by selecting on uid, train no, and checkin/checkout station ID.
	my $rows = $db->update(
		'in_transit',
		{
			cancelled => 1,
		},
		{
			user_id             => $uid,
			train_no            => $train->train_no,
			checkin_station_id  => $dep_eva,
			checkout_station_id => $arr_eva,
		}
	)->rows;

	return $rows;
}

sub update_arrival {
	my ( $self, %opt ) = @_;
	my $uid     = $opt{uid};
	my $db      = $opt{db} // $self->{pg}->db;
	my $arr_eva = $opt{arr_eva};
	my $train   = $opt{train};
	my $json    = JSON->new;

	# selecting on user_id, train_no and checkout_station_id avoids a
	# race condition when a user checks into a new train or changes
	# their destination station while we are fetching times based on no
	# longer valid database entries.
	my $rows = $db->update(
		'in_transit',
		{
			arr_platform  => $train->platform,
			sched_arrival => $train->sched_arrival,
			real_arrival  => $train->arrival,
			route         => $json->encode( $opt{route} ),
			messages      => $json->encode(
				[ map { [ $_->[0]->epoch, $_->[1] ] } $train->messages ]
			),
		},
		{
			user_id             => $uid,
			train_no            => $train->train_no,
			checkout_station_id => $arr_eva,
		}
	)->rows;

	return $rows;
}

sub update_data {
	my ( $self, %opt ) = @_;